📄 elfls.c
字号:
* string table) and looking up symbols of type STT_FILE. */static int getsrcfiles(textline **plines){ Elf32_Sym *syms; char *nmstr; textline *lines; char *str; unsigned strtab, count, i; int j, n; if (!secthdrs) return 0; for (i = 0 ; i < elffhdr.e_shnum ; ++i) if (secthdr[i].sh_type == SHT_SYMTAB) break; if (i == elffhdr.e_shnum) return 0; if (!(syms = getarea(secthdr[i].sh_offset, secthdr[i].sh_size))) return 0; strtab = secthdr[i].sh_link; if (!(nmstr = getarea(secthdr[strtab].sh_offset, secthdr[strtab].sh_size))) return 0; count = secthdr[i].sh_size / sizeof *syms; lines = gettextlines(count); n = 0; for (i = 0 ; i < count ; ++i) { if (ELF32_ST_TYPE(syms[i].st_info) != STT_FILE) continue; str = nmstr + syms[i].st_name; for (j = 0 ; j < n ; ++j) if (!strcmp(lines[j].str, str)) break; if (j == n) append(lines + n++, "%s", str); } free(syms); free(nmstr); if (n) *plines = lines; else free(lines); return n;}/* Extract the list of dependencies, if present. The program header * table entry of type PT_DYNAMIC contains the dynamic info, which * includes the dependent files, and the string table that contains * the file names. However, the string table is referenced by its * location in memory, as opposed to its location in the file, so * the program header table needs to be searched again to find the * part that will be loaded at that location. */static int getlibraries(textline **plines){ Elf32_Dyn *dyns; char *nmstr; textline *lines; char *str; unsigned strtab = 0, strsz = 0, count, i, j, n; if (!proghdrs) return 0; for (i = 0 ; i < elffhdr.e_phnum ; ++i) if (proghdr[i].p_type == PT_DYNAMIC) break; if (i == elffhdr.e_phnum) return 0; if (!(dyns = getarea(proghdr[i].p_offset, proghdr[i].p_filesz))) return 0; count = proghdr[i].p_filesz / sizeof *dyns; n = 0; for (i = 0 ; i < count ; ++i) { if (dyns[i].d_tag == DT_STRTAB) strtab = dyns[i].d_un.d_ptr; else if (dyns[i].d_tag == DT_STRSZ) strsz = dyns[i].d_un.d_val; else if (dyns[i].d_tag == DT_NEEDED) ++n; } if (!strtab || !strsz) return 0; for (i = 0 ; i < elffhdr.e_phnum ; ++i) if (strtab >= proghdr[i].p_vaddr && strtab < proghdr[i].p_vaddr + proghdr[i].p_filesz) break; if (i == elffhdr.e_phnum) return 0; if (!(nmstr = getarea(proghdr[i].p_offset + (strtab - proghdr[i].p_vaddr), strsz))) return 0; lines = gettextlines(n); n = 0; for (i = 0 ; i < count ; ++i) { if (dyns[i].d_tag != DT_NEEDED) continue; str = nmstr + dyns[i].d_un.d_val; for (j = 0 ; j < n ; ++j) if (!strcmp(lines[j].str, str)) break; if (j == n) append(lines + n++, "%s", str); } free(dyns); free(nmstr); if (n) *plines = lines; else free(lines); return n;}/* * Output-generating functions. */static void describeehdr(FILE *fp){ fprintf(fp, "%s", thefilename); switch (elffhdr.e_type) { case ET_REL: break; case ET_EXEC: fputc('*', fp); break; case ET_DYN: fputc('&', fp); break; default: fprintf(fp, "?(%u)", elffhdr.e_type); break; } switch (elffhdr.e_machine) { case EM_M32: fprintf(fp, " (AT&T M32)"); break; case EM_386: fprintf(fp, " (Intel 386)"); break; case EM_860: fprintf(fp, " (Intel 860)"); break; case EM_MIPS: fprintf(fp, " (MIPS)"); break; case EM_68K: fprintf(fp, " (Motorola 68k)"); break; case EM_88K: fprintf(fp, " (Motorola 88k)"); break; case EM_SPARC: fprintf(fp, " (SPARC)"); break; default: fprintf(fp, " (?%u)", elffhdr.e_machine); break; } fputc('\n', fp);}/* Fill the given string with the terse description of the given * program header table entry. The description includes a character * that identifies the entry type, the segment permission flags, the * offset and size within the file, and the virtual address at which * to load the contents. */static void describephdr(textline *line, Elf32_Phdr *phdr){ char const *str; int n; switch (phdr->p_type) { case PT_NULL: append(line, "(null)"); return; case PT_INTERP: append(line, "I "); break; case PT_NOTE: append(line, "N "); break; case PT_LOAD: append(line, "P "); break; case PT_PHDR: append(line, "T "); break; case PT_DYNAMIC: append(line, "L "); break; default: append(line, "? "); break; } if (dostrs) { switch (phdr->p_type) { case PT_INTERP: str = getstring(phdr->p_offset, phdr->p_filesz, FALSE); if (str && *str) { n = strlen(str); if (n > 30) append(line, "\"%.27s...\"", str); else append(line, "\"%s\"", str); return; } break; case PT_NOTE: str = getstring(phdr->p_offset + 12, phdr->p_filesz - 12, FALSE); if (str && *str) { n = strlen(str); if (n > 30) append(line, "\"%.27s...\"", str); else append(line, "\"%s\"", str); return; } break; } } append(line, "%c%c%c", (phdr->p_flags & PF_R ? 'r' : '-'), (phdr->p_flags & PF_W ? 'w' : '-'), (phdr->p_flags & PF_X ? phdr == phentry ? 's' : 'x' : '-')); if (dooffs) append(line, "%6lX", phdr->p_offset); append(line, "%6lX %08lX", phdr->p_filesz, phdr->p_vaddr); if (phdr->p_filesz != phdr->p_memsz) append(line, " +%lX", phdr->p_memsz - phdr->p_filesz);}/* Fill the given string with the terse description of the given * section header table entry. The description includes a character * that identifies the entry type, the flags, the offset and size * within the file, and the section name and the indices of any * related sections. */static void describeshdr(textline *line, Elf32_Shdr *shdr){ char const *str; int n; switch (shdr->sh_type) { case SHT_NULL: append(line, "(null)"); return; case SHT_PROGBITS: if (sectstr) { str = sectstr + shdr->sh_name; if (!strcmp(str, ".comment")) { append(line, "C "); if (dostrs) { str = getstring(shdr->sh_offset, shdr->sh_size, TRUE); if (str && *str) { n = strlen(str); if (n > 30) append(line, "\"%.27s...\"", str); else append(line, "\"%s\"", str); return; } } break; } else if (!strcmp(str, ".interp")) { append(line, "I "); if (dostrs) { str = getstring(shdr->sh_offset, shdr->sh_size, FALSE); if (str && *str) { n = strlen(str); if (n > 30) append(line, "\"%.27s...\"", str); else append(line, "\"%s\"", str); return; } } break; } } append(line, "P "); break; case SHT_NOTE: append(line, "N "); break; case SHT_STRTAB: append(line, "$ "); break; case SHT_SYMTAB: append(line, "S "); break; case SHT_DYNSYM: append(line, "D "); break; case SHT_DYNAMIC: append(line, "L "); break; case SHT_REL: append(line, "R "); break; case SHT_RELA: append(line, "A "); break; case SHT_HASH: append(line, "H "); break; case SHT_NOBITS: append(line, "0 "); break;#ifdef SHT_GNU_verdef case SHT_GNU_verdef: append(line, "U "); break;#endif#ifdef SHT_GNU_verneed case SHT_GNU_verneed: append(line, "V "); break;#endif#ifdef SHT_GNU_versym case SHT_GNU_versym: append(line, "W "); break;#endif default: append(line, "? "); break; } if (dostrs) { if (shdr->sh_type == SHT_NOTE) { str = getstring(shdr->sh_offset + 12, shdr->sh_size - 12, FALSE); if (str && *str) { n = strlen(str); if (n > 30) append(line, "\"%.27s...\"", str); else append(line, "\"%s\"", str); return; } } } append(line, "%c%c%c", (shdr->sh_flags & SHF_ALLOC ? 'r' : '-'), (shdr->sh_flags & SHF_WRITE ? 'w' : '-'), (shdr->sh_flags & SHF_EXECINSTR ? 'x' : '-')); if (dooffs) append(line, "%6lX", shdr->sh_offset); append(line, "%6lX %s", shdr->sh_size, sectstr ? sectstr + shdr->sh_name : "(n/a)"); if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) append(line, ":%lu", shdr->sh_info); if (shdr->sh_link) append(line, " [%lu]", shdr->sh_link); if (shdr->sh_type == SHT_STRTAB && shdr == shshstr) append(line, " [S]");}/* * Top-level functions. *//* Parse the command-line options. */static void readoptions(int argc, char *argv[]){ char const *str; int n; if (!(str = getenv("COLUMNS")) || (outwidth = atoi(str)) <= 0) outwidth = 80; while ((n = getopt(argc, argv, "cdEhiPpSvw:")) != EOF) { switch (n) { case 'h': fputs(yowzitch, stdout); exit(EXIT_SUCCESS); case 'v': fputs(vourzhon, stdout); exit(EXIT_SUCCESS); case 'E': skipID = TRUE; break; case 'c': srcfls = TRUE; break; case 'd': ldepls = TRUE; break; case 'P': phdrls = FALSE; break; case 'S': shdrls = FALSE; break; case 'i': dostrs = FALSE; break; case 'p': dooffs = FALSE; break; case 'w': if ((outwidth = atoi(optarg)) < 0) { fputs(yowzitch, stderr); exit(EXIT_FAILURE); } break; default: fputs(yowzitch, stderr); exit(EXIT_FAILURE); } }}/* main(). */int main(int argc, char *argv[]){ textline *lines; char **arg; int ret = 0; int count, i; thisprog = argv[0]; readoptions(argc, argv); for (arg = argv + optind ; (thefilename = *arg) != NULL ; ++arg) { if (!(thefile = fopen(thefilename, "rb"))) { perror(thefilename); ++ret; continue; } if (!readelfhdr() || !readproghdrs() || !readsecthdrs()) { fclose(thefile); ++ret; continue; } describeehdr(stdout); if (ldepls && proghdrs) { if ((count = getlibraries(&lines))) { outputlist(stdout, lines, count, "Dependencies: "); free(lines); } } if (srcfls && secthdrs) { if ((count = getsrcfiles(&lines))) { qsort(lines, count, sizeof *lines, linesorter); outputlist(stdout, lines, count, "Source files: "); free(lines); } } if (phdrls && proghdrs) { printf("Program header table entries: %d", elffhdr.e_phnum); if (dooffs) printf(" (%lX - %lX)", (unsigned long)elffhdr.e_phoff, (unsigned long)elffhdr.e_phoff + elffhdr.e_phnum * elffhdr.e_phentsize); putchar('\n'); lines = gettextlines(elffhdr.e_phnum); for (i = 0 ; i < elffhdr.e_phnum ; ++i) { append(lines + i, "%2d ", i); describephdr(lines + i, proghdr + i); } formatlist(stdout, lines, elffhdr.e_phnum); free(lines); } if (shdrls && secthdrs) { printf("Section header table entries: %d", elffhdr.e_shnum); if (dooffs) printf(" (%lX - %lX)", (unsigned long)elffhdr.e_shoff, (unsigned long)elffhdr.e_shoff + elffhdr.e_shnum * elffhdr.e_shentsize); putchar('\n'); lines = gettextlines(elffhdr.e_shnum); for (i = 0 ; i < elffhdr.e_shnum ; ++i) { append(lines + i, "%2d ", i); describeshdr(lines + i, secthdr + i); } formatlist(stdout, lines, elffhdr.e_shnum); free(lines); } fclose(thefile); free(proghdr); free(secthdr); free(sectstr); } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -