summaryrefslogtreecommitdiff
path: root/usr/src/cmd/file/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/file/file.c')
-rw-r--r--usr/src/cmd/file/file.c502
1 files changed, 104 insertions, 398 deletions
diff --git a/usr/src/cmd/file/file.c b/usr/src/cmd/file/file.c
index 1b6a7209d1..b988a755f5 100644
--- a/usr/src/cmd/file/file.c
+++ b/usr/src/cmd/file/file.c
@@ -63,8 +63,7 @@
#include <elfcap.h>
#include <sgsrtcid.h>
#include "file.h"
-
-typedef Elf64_Nhdr GElf_Nhdr;
+#include "elf_read.h"
/*
* Misc
@@ -133,7 +132,6 @@ static char *as[] = { /* Assembler Pseudo Ops, prepended with '.' */
static char *debug_sections[] = { /* Debug sections in a ELF file */
".debug", ".stab", ".dwarf", ".line", NULL};
-
/* start for MB env */
static wchar_t wchar;
static int length;
@@ -161,8 +159,6 @@ static char **mlist2p; /* next entry in mlist2 */
static ssize_t mread;
-static void is_stripped(Elf *elf);
-static Elf *is_elf_file(int elffd);
static void ar_coff_or_aout(int ifd);
static int type(char *file);
static int def_position_tests(char *file);
@@ -173,10 +169,8 @@ static int ccom(void);
static int ascom(void);
static int sccs(void);
static int english(char *bp, int n);
-static int old_core(Elf *elf, GElf_Ehdr *ehdr, int format);
-static int core(Elf *elf, GElf_Ehdr *ehdr, int format, char *file);
static int shellscript(char buf[], struct stat64 *sb);
-static int elf_check(Elf *elf, char *file);
+static int elf_check(char *file);
static int get_door_target(char *, char *, size_t);
static int zipfile(char *, int);
static int is_crash_dump(const char *, int);
@@ -184,13 +178,16 @@ static void print_dumphdr(const int, const dumphdr_t *, uint32_t (*)(uint32_t),
const char *);
static uint32_t swap_uint32(uint32_t);
static uint32_t return_uint32(uint32_t);
-static int is_in_list(char *[], char *);
static void usage(void);
static void default_magic(void);
static void add_to_mlist(char *, int);
static void fd_cleanup(void);
static int is_rtld_config(void);
+/* from elf_read.c */
+int elf_read32(int elffd, Elf_Info *EInfo);
+int elf_read64(int elffd, Elf_Info *EInfo);
+
#ifdef XPG4
/* SUSv3 requires a single <space> after the colon */
#define prf(x) (void) printf("%s: ", x);
@@ -620,21 +617,16 @@ spcl:
static int
def_position_tests(char *file)
{
- Elf *elf;
-
if (sccs()) { /* look for "1hddddd" where d is a digit */
(void) printf("sccs \n");
return (1);
}
if (fbuf[0] == '#' && fbuf[1] == '!' && shellscript(fbuf+2, &mbuf))
return (1);
- if ((elf = is_elf_file(elffd)) != NULL) {
- (void) elf_check(elf, file);
- (void) elf_end(elf);
+
+ if (elf_check(file) == 0) {
(void) putchar('\n');
return (1);
-
-
/* LINTED: pointer cast may result in improper alignment */
} else if (*(int *)fbuf == CORE_MAGIC) {
/* LINTED: pointer cast may result in improper alignment */
@@ -922,27 +914,6 @@ troffint(char *bp, int n)
return (1);
}
-/*
- * Determine if the passed descriptor describes an ELF file.
- * If so, return the Elf handle.
- */
-static Elf *
-is_elf_file(int elffd)
-{
- Elf *elf;
-
- elf = elf_begin(elffd, ELF_C_READ, (Elf *)0);
- switch (elf_kind(elf)) {
- case ELF_K_ELF:
- break;
- default:
- (void) elf_end(elf);
- elf = NULL;
- break;
- }
- return (elf);
-}
-
static void
ar_coff_or_aout(int elffd)
{
@@ -976,9 +947,9 @@ ar_coff_or_aout(int elffd)
static void
-print_elf_type(Elf *elf, GElf_Ehdr *ehdr, int format)
+print_elf_type(Elf_Info EI)
{
- switch (ehdr->e_type) {
+ switch (EI.type) {
case ET_NONE:
(void) printf(" %s", gettext("unknown type"));
break;
@@ -991,12 +962,6 @@ print_elf_type(Elf *elf, GElf_Ehdr *ehdr, int format)
case ET_DYN:
(void) printf(" %s", gettext("dynamic lib"));
break;
- case ET_CORE:
- if (old_core(elf, ehdr, format))
- (void) printf(" %s", gettext("pre-2.6 core file"));
- else
- (void) printf(" %s", gettext("core file"));
- break;
default:
break;
}
@@ -1152,9 +1117,12 @@ print_elf_class(int class)
}
static void
-print_elf_flags(int machine, unsigned int flags)
+print_elf_flags(Elf_Info EI)
{
- switch (machine) {
+ unsigned int flags;
+
+ flags = EI.flags;
+ switch (EI.machine) {
case EM_SPARCV9:
if (flags & EF_SPARC_EXT_MASK) {
if (flags & EF_SPARC_SUN_US3) {
@@ -1188,221 +1156,125 @@ print_elf_flags(int machine, unsigned int flags)
}
}
+/*
+ * check_ident: checks the ident field of the presumeably
+ * elf file. If check fails, this is not an
+ * elf file.
+ */
static int
-print_cap(Elf *elf, GElf_Ehdr *ehdr, char *file)
+check_ident(unsigned char *ident, int fd)
{
- Elf_Scn *scn = 0;
-
- /*
- * Traverse the files sections to see if any software/hardware
- * capabilities are available.
- */
- while ((scn = elf_nextscn(elf, scn)) != 0) {
- GElf_Word ndx, capn;
- GElf_Shdr shdr;
- Elf_Data *data;
-
- if (gelf_getshdr(scn, &shdr) == 0) {
- (void) fprintf(stderr, gettext("%s: %s: can't read "
- "ELF section header - ELF capabilities ignored\n"),
- File, file);
- return (1);
- }
- if (shdr.sh_type != SHT_SUNW_cap)
- continue;
-
- /*
- * Get the data associated with the .cap section.
- */
- if ((data = elf_getdata(scn, 0)) == 0) {
- (void) fprintf(stderr, gettext("%s: %s: can't read "
- "ELF section data - ELF capabilities ignored\n"),
- File, file);
- return (1);
- }
-
- if ((shdr.sh_size == 0) || (shdr.sh_entsize == 0)) {
- (void) fprintf(stderr, gettext("%s: %s zero size or "
- "zero entry ELF section - ELF capabilities "
- "ignored\n"), File, file);
- return (1);
- }
- capn = (GElf_Word)(shdr.sh_size / shdr.sh_entsize);
-
- for (ndx = 0; ndx < capn; ndx++) {
- char str[100];
- GElf_Cap cap;
-
- if (gelf_getcap(data, ndx, &cap) == NULL) {
- (void) fprintf(stderr, gettext("%s: %s: can't "
- "read ELF capabilities data - ELF "
- "capabilities ignored\n"), File, file);
- return (1);
- }
- if (cap.c_tag != CA_SUNW_NULL) {
- (void) cap_val2str(cap.c_tag, cap.c_un.c_val,
- str, sizeof (str), 0, ehdr->e_machine);
- (void) printf(" [%s]", str);
- }
- }
- }
- return (0);
+ int class;
+ if (pread64(fd, ident, EI_NIDENT, 0) != EI_NIDENT)
+ return (ELF_READ_FAIL);
+ class = ident[EI_CLASS];
+ if (class != ELFCLASS32 && class != ELFCLASS64)
+ return (ELF_READ_FAIL);
+ if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
+ ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3)
+ return (ELF_READ_FAIL);
+
+ return (ELF_READ_OKAY);
}
static int
-elf_check(Elf *elf, char *file)
+elf_check(char *file)
{
- GElf_Ehdr ehdr;
- GElf_Phdr phdr;
- int dynamic, cnt;
- char *ident;
- size_t size;
+ Elf_Info EInfo;
+ int class, version, format;
+ unsigned char ident[EI_NIDENT];
- /*
- * Verify information in file header.
- */
- if (gelf_getehdr(elf, &ehdr) == (GElf_Ehdr *)0) {
- (void) fprintf(stderr, gettext("%s: %s: can't read ELF "
- "header\n"), File, file);
- return (1);
- }
- ident = elf_getident(elf, &size);
- (void) printf("%s", gettext("ELF"));
- print_elf_class(ident[EI_CLASS]);
- print_elf_datatype(ident[EI_DATA]);
- print_elf_type(elf, &ehdr, ident[EI_DATA]);
- print_elf_machine(ehdr.e_machine);
- if (ehdr.e_version == 1)
- (void) printf(" %s %d",
- gettext("Version"), (int)ehdr.e_version);
- print_elf_flags(ehdr.e_machine, ehdr.e_flags);
-
- if (core(elf, &ehdr, ident[EI_DATA], file)) /* check for core file */
- return (0);
-
- if (print_cap(elf, &ehdr, file))
- return (1);
+ (void) memset(&EInfo, 0, sizeof (Elf_Info));
+ EInfo.file = file;
/*
- * Check type.
+ * Verify information in file indentifier.
+ * Return quietly if not elf; Different type of file.
*/
- if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN))
+ if (check_ident(ident, elffd) == ELF_READ_FAIL)
return (1);
/*
- * Read program header and check for dynamic section.
+ * Read the elf headers for processing and get the
+ * get the needed information in Elf_Info struct.
*/
- if (ehdr.e_phnum == 0) {
- (void) fprintf(stderr, gettext("%s: %s: no ELF program headers "
- "exist\n"), File, file);
- return (1);
- }
-
- for (dynamic = 0, cnt = 0; cnt < (int)ehdr.e_phnum; cnt++) {
- if (gelf_getphdr(elf, cnt, &phdr) == NULL) {
- (void) fprintf(stderr, gettext("%s: %s: can't read "
- "ELF program header\n"), File, file);
+ class = ident[EI_CLASS];
+ if (class == ELFCLASS32) {
+ if (elf_read32(elffd, &EInfo) == ELF_READ_FAIL) {
+ (void) fprintf(stderr, gettext("%s: %s: can't "
+ "read ELF header\n"), File, file);
return (1);
}
- if (phdr.p_type == PT_DYNAMIC) {
- dynamic = 1;
- break;
+ } else if (class == ELFCLASS64) {
+ if (elf_read64(elffd, &EInfo) == ELF_READ_FAIL) {
+ (void) fprintf(stderr, gettext("%s: %s: can't "
+ "read ELF header\n"), File, file);
+ return (1);
}
+ } else {
+ /* something wrong */
+ return (1);
}
- if (dynamic)
- (void) printf(gettext(", dynamically linked"));
- else
- (void) printf(gettext(", statically linked"));
- is_stripped(elf);
- return (0);
-}
-
-/*
- * is_stripped prints information on whether the executable has
- * been stripped.
- */
-static void
-is_stripped(Elf *elf)
-{
- GElf_Shdr shdr;
- GElf_Ehdr ehdr;
- Elf_Scn *scn, *nextscn;
- char *section_name;
- int symtab = 0;
- int debuginfo = 0;
+ /* version not in ident then 1 */
+ version = ident[EI_VERSION] ? ident[EI_VERSION] : 1;
+ format = ident[EI_DATA];
+ (void) printf("%s", gettext("ELF"));
+ print_elf_class(class);
+ print_elf_datatype(format);
+ print_elf_type(EInfo);
- if (gelf_getehdr(elf, &ehdr) == NULL) {
- return;
+ if (EInfo.core_type != EC_NOTCORE) {
+ /* Print what kind of core is this */
+ if (EInfo.core_type == EC_OLDCORE)
+ (void) printf(" %s", gettext("pre-2.6 core file"));
+ else
+ (void) printf(" %s", gettext("core file"));
}
- /*
- * Definition time:
- * - "not stripped" means that an executable file
- * contains a Symbol Table (.symtab)
- * - "stripped" means that an executable file
- * does not contain a Symbol Table.
- * When strip -l or strip -x is run, it strips the
- * debugging information (.line section name (strip -l),
- * .line, .debug*, .stabs*, .dwarf* section names
- * and SHT_SUNW_DEBUGSTR and SHT_SUNW_DEBUG
- * section types (strip -x), however the Symbol
- * Table will still be present.
- * Therefore, if
- * - No Symbol Table present, then report
- * "stripped"
- * - Symbol Table present with debugging
- * information (line number or debug section names,
- * or SHT_SUNW_DEBUGSTR or SHT_SUNW_DEBUG section
- * types) then report:
- * "not stripped"
- * - Symbol Table present with no debugging
- * information (line number or debug section names,
- * or SHT_SUNW_DEBUGSTR or SHT_SUNW_DEBUG section
- * types) then report:
- * "not stripped, no debugging information
- * available"
- */
- scn = NULL;
- while ((nextscn = elf_nextscn(elf, scn)) != NULL) {
- if (symtab && debuginfo) {
- break;
- }
+ /* Print machine info */
+ print_elf_machine(EInfo.machine);
- scn = nextscn;
- if (gelf_getshdr(scn, &shdr) == NULL) {
- continue;
- }
+ /* Print Version */
+ if (version == 1)
+ (void) printf(" %s %d", gettext("Version"), version);
- if (!symtab && (shdr.sh_type == SHT_SYMTAB)) {
- symtab++;
- continue;
- }
+ /* Print Flags */
+ print_elf_flags(EInfo);
- if (!debuginfo &&
- ((shdr.sh_type == SHT_SUNW_DEBUG) ||
- (shdr.sh_type == SHT_SUNW_DEBUGSTR) ||
- (((section_name = elf_strptr(elf, ehdr.e_shstrndx,
- (size_t)shdr.sh_name)) != NULL) &&
- (is_in_list(debug_sections, section_name))))) {
- debuginfo++;
- }
+ /* Last bit, if it is a core */
+ if (EInfo.core_type != EC_NOTCORE) {
+ /* Print the program name that dumped this core */
+ (void) printf(gettext(", from '%s'"), EInfo.fname);
+ return (0);
}
- /*
- * Now that we've scanned all sections, print out the appropriate
- * diagnostic.
- */
- if (symtab) {
+ /* Print Capabilities */
+ if (EInfo.cap_str[0] != '\0')
+ (void) printf(" [%s]", EInfo.cap_str);
+
+ if ((EInfo.type != ET_EXEC) && (EInfo.type != ET_DYN))
+ return (0);
+
+ /* Print if it is dynamically linked */
+ if (EInfo.dynamic)
+ (void) printf(gettext(", dynamically linked"));
+ else
+ (void) printf(gettext(", statically linked"));
+
+ /* Printf it it is stripped */
+ if (EInfo.stripped & E_SYMTAB) {
(void) printf(gettext(", not stripped"));
- if (!debuginfo) {
+ if (!(EInfo.stripped & E_DBGINF)) {
(void) printf(gettext(
", no debugging information available"));
}
} else {
(void) printf(gettext(", stripped"));
}
+
+ return (0);
}
/*
@@ -1580,173 +1452,6 @@ english(char *bp, int n)
return (vow * 5 >= n - ct[' '] && freq >= 10 * rare);
}
-/*
- * Convert a word from an elf file to native format.
- * This is needed because there's no elf routine to
- * get and decode a Note section header.
- */
-static void
-convert_gelf_word(Elf *elf, GElf_Word *data, int version, int format)
-{
- Elf_Data src, dst;
-
- dst.d_buf = data;
- dst.d_version = version;
- dst.d_size = sizeof (GElf_Word);
- dst.d_type = ELF_T_WORD;
- src.d_buf = data;
- src.d_version = version;
- src.d_size = sizeof (GElf_Word);
- src.d_type = ELF_T_WORD;
- (void) gelf_xlatetom(elf, &dst, &src, format);
-}
-
-static void
-convert_gelf_nhdr(Elf *elf, GElf_Nhdr *nhdr, GElf_Word version, int format)
-{
- convert_gelf_word(elf, &nhdr->n_namesz, version, format);
- convert_gelf_word(elf, &nhdr->n_descsz, version, format);
- convert_gelf_word(elf, &nhdr->n_type, version, format);
-}
-
-/*
- * Return true if it is an old (pre-restructured /proc) core file.
- */
-static int
-old_core(Elf *elf, GElf_Ehdr *ehdr, int format)
-{
- register int inx;
- GElf_Phdr phdr;
- GElf_Phdr nphdr;
- GElf_Nhdr nhdr;
- off_t offset;
-
- if (ehdr->e_type != ET_CORE)
- return (0);
- for (inx = 0; inx < (int)ehdr->e_phnum; inx++) {
- if (gelf_getphdr(elf, inx, &phdr) == NULL) {
- return (0);
- }
- if (phdr.p_type == PT_NOTE) {
- /*
- * If the next segment is also a note, use it instead.
- */
- if (gelf_getphdr(elf, inx+1, &nphdr) == NULL) {
- return (0);
- }
- if (nphdr.p_type == PT_NOTE)
- phdr = nphdr;
- offset = (off_t)phdr.p_offset;
- (void) pread(ifd, &nhdr, sizeof (GElf_Nhdr), offset);
- convert_gelf_nhdr(elf, &nhdr, ehdr->e_version, format);
- /*
- * Old core files have type NT_PRPSINFO.
- */
- if (nhdr.n_type == NT_PRPSINFO)
- return (1);
- return (0);
- }
- }
- return (0);
-}
-
-/*
- * If it's a core file, print out the name of the file that dumped core.
- */
-static int
-core(Elf *elf, GElf_Ehdr *ehdr, int format, char *file)
-{
- register int inx;
- char *psinfo;
- GElf_Phdr phdr;
- GElf_Phdr nphdr;
- GElf_Nhdr nhdr;
- off_t offset;
-
- if (ehdr->e_type != ET_CORE)
- return (0);
- for (inx = 0; inx < (int)ehdr->e_phnum; inx++) {
- if (gelf_getphdr(elf, inx, &phdr) == NULL) {
- (void) fprintf(stderr, gettext("%s: %s: can't read "
- "ELF program header\n"), File, file);
- return (0);
- }
- if (phdr.p_type == PT_NOTE) {
- char *fname;
- size_t size;
-
- /*
- * If the next segment is also a note, use it instead.
- */
- if (gelf_getphdr(elf, inx+1, &nphdr) == NULL) {
- (void) fprintf(stderr, gettext("%s: %s: can't "
- "read ELF program header\n"), File, file);
- return (0);
- }
- if (nphdr.p_type == PT_NOTE)
- phdr = nphdr;
- offset = (off_t)phdr.p_offset;
- (void) pread(ifd, &nhdr, sizeof (GElf_Nhdr), offset);
- convert_gelf_nhdr(elf, &nhdr, ehdr->e_version, format);
-
- /*
- * Note: the ABI states that n_namesz must
- * be rounded up to a 4 byte boundary.
- */
- offset += sizeof (GElf_Nhdr) +
- ((nhdr.n_namesz + 0x03) & ~0x3);
- size = nhdr.n_descsz;
- if ((psinfo = malloc(size)) == NULL) {
- int err = errno;
- (void) fprintf(stderr, gettext("%s: malloc "
- "failed: %s\n"), File, strerror(err));
- exit(2);
- }
- (void) pread(ifd, psinfo, size, offset);
-
- /*
- * We want to print the string contained
- * in psinfo->pr_fname[], where 'psinfo'
- * is either an old NT_PRPSINFO structure
- * or a new NT_PSINFO structure.
- *
- * Old core files have only type NT_PRPSINFO.
- * New core files have type NT_PSINFO.
- *
- * These structures are also different by
- * virtue of being contained in a core file
- * of either 32-bit or 64-bit type.
- *
- * To further complicate matters, we ourself
- * might be compiled either 32-bit or 64-bit.
- *
- * For these reason, we just *know* the offsets of
- * pr_fname[] into the four different structures
- * here, regardless of how we are compiled.
- */
- if (gelf_getclass(elf) == ELFCLASS32) {
- /* 32-bit core file, 32-bit structures */
- if (nhdr.n_type == NT_PSINFO)
- fname = psinfo + 88;
- else /* old: NT_PRPSINFO */
- fname = psinfo + 84;
- } else if (gelf_getclass(elf) == ELFCLASS64) {
- /* 64-bit core file, 64-bit structures */
- if (nhdr.n_type == NT_PSINFO)
- fname = psinfo + 136;
- else /* old: NT_PRPSINFO */
- fname = psinfo + 120;
- } else {
- free(psinfo);
- break;
- }
- (void) printf(gettext(", from '%s'"), fname);
- free(psinfo);
- break;
- }
- }
- return (1);
-}
static int
shellscript(char buf[], struct stat64 *sb)
@@ -1966,8 +1671,8 @@ return_uint32(uint32_t in)
/*
* Check if str is in the string list str_list.
*/
-static int
-is_in_list(char *str_list[], char *str)
+int
+is_in_list(char *str)
{
int i;
@@ -1976,8 +1681,9 @@ is_in_list(char *str_list[], char *str)
* That way .stab will match on .stab* sections, and
* .debug will match on .debug* sections.
*/
- for (i = 0; str_list[i] != NULL; i++) {
- if (strncmp(str_list[i], str, strlen(str_list[i])) == 0) {
+ for (i = 0; debug_sections[i] != NULL; i++) {
+ if (strncmp(debug_sections[i], str,
+ strlen(debug_sections[i])) == 0) {
return (1);
}
}