summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/file/Makefile23
-rw-r--r--usr/src/cmd/file/elf_read.c476
-rw-r--r--usr/src/cmd/file/elf_read.h104
-rw-r--r--usr/src/cmd/file/file.c502
-rw-r--r--usr/src/cmd/file/req.flg8
5 files changed, 708 insertions, 405 deletions
diff --git a/usr/src/cmd/file/Makefile b/usr/src/cmd/file/Makefile
index 5038c27713..453e77ec27 100644
--- a/usr/src/cmd/file/Makefile
+++ b/usr/src/cmd/file/Makefile
@@ -32,15 +32,20 @@ MAGIC= magic
ELFCAP= $(SRC)/common/elfcap
SGSRTCID= $(SRC)/common/sgsrtcid
-LOBJS= file.o magicutils.o
+LOBJS= file.o elf_read32.o elf_read64.o magicutils.o
OBJS= $(LOBJS) elfcap.o
XPG4OBJS= $(OBJS:%.o=xpg4_%.o)
-SRCS= $(LOBJS:%.o=%.c) $(ELFCAP)/elfcap.c
+SRCS= file.c elf_read.c magicutils.c $(ELFCAP)/elfcap.c
include ../Makefile.cmd
POFILE= file_all.po
-POFILES= $(LOBJS:%.o=%.po)
+POFILES= $(SRCS:%.c=%.po)
+
+# The debug binary can be built using the flag
+# -D COPTFLAG=-g CGLOBALSTATIC=
+# This will avoid the multiple symbols definition error
+# for static global variables in elf_read32.o and elf_read64.o
LDLIBS += -lelf
CPPFLAGS += -DCAP_UPPERCASE -I$(ELFCAP) -I$(SGSRTCID)
@@ -67,9 +72,21 @@ $(XPG4) : $(XPG4OBJS)
%.o: %.c
$(COMPILE.c) -o $@ $<
+%32.o: %.c
+ $(COMPILE.c) -o $@ $<
+
+%64.o: %.c
+ $(COMPILE.c) -D_ELF64 -o $@ $<
+
xpg4_%.o: %.c
$(COMPILE.c) -o $@ $<
+xpg4_%32.o: %.c
+ $(COMPILE.c) -o $@ $<
+
+xpg4_%64.o: %.c
+ $(COMPILE.c) -D_ELF64 -o $@ $<
+
elfcap.o: $(ELFCAP)/elfcap.c
$(COMPILE.c) -o $@ $(ELFCAP)/elfcap.c
diff --git a/usr/src/cmd/file/elf_read.c b/usr/src/cmd/file/elf_read.c
new file mode 100644
index 0000000000..905c37b586
--- /dev/null
+++ b/usr/src/cmd/file/elf_read.c
@@ -0,0 +1,476 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/* Copyright (c) 1987, 1988 Microsoft Corporation */
+/* All Rights Reserved */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define _LARGEFILE64_SOURCE
+
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <libelf.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <locale.h>
+#include <string.h>
+#include <errno.h>
+#include <procfs.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/elf.h>
+#include <elfcap.h>
+#include "file.h"
+#include "elf_read.h"
+
+extern const char *File;
+
+static int get_class(void);
+static int get_version(void);
+static int get_format(void);
+static int process_shdr(Elf_Info *);
+static int process_phdr(Elf_Info *);
+static int file_xlatetom(Elf_Type, char *);
+static int xlatetom_nhdr(Elf_Nhdr *);
+static int get_phdr(Elf_Info *, int);
+static int get_shdr(Elf_Info *, int);
+
+static Elf_Ehdr EI_Ehdr; /* Elf_Ehdr to be stored */
+static Elf_Shdr EI_Shdr; /* recent Elf_Shdr to be stored */
+static Elf_Phdr EI_Phdr; /* recent Elf_Phdr to be stored */
+
+
+static int
+get_class(void)
+{
+ return (EI_Ehdr.e_ident[EI_CLASS]);
+}
+
+static int
+get_version(void)
+{
+ /* do as what libelf:_elf_config() does */
+ return (EI_Ehdr.e_ident[EI_VERSION] ?
+ EI_Ehdr.e_ident[EI_VERSION] : 1);
+}
+
+static int
+get_format(void)
+{
+ return (EI_Ehdr.e_ident[EI_DATA]);
+}
+
+/*
+ * file_xlatetom: translate different headers from file
+ * representation to memory representaion.
+ */
+#define HDRSZ 512
+static int
+file_xlatetom(Elf_Type type, char *hdr)
+{
+ Elf_Data src, dst;
+ char *hbuf[HDRSZ];
+ int version, format;
+
+ version = get_version();
+ format = get_format();
+
+ /* will convert only these types */
+ if (type != ELF_T_EHDR && type != ELF_T_PHDR &&
+ type != ELF_T_SHDR && type != ELF_T_WORD &&
+ type != ELF_T_CAP)
+ return (ELF_READ_FAIL);
+
+ src.d_buf = (Elf_Void *)hdr;
+ src.d_type = type;
+ src.d_version = version;
+
+ dst.d_buf = (Elf_Void *)&hbuf;
+ dst.d_version = EV_CURRENT;
+
+ src.d_size = elf_fsize(type, 1, version);
+ dst.d_size = elf_fsize(type, 1, EV_CURRENT);
+ if (elf_xlatetom(&dst, &src, format) == NULL)
+ return (ELF_READ_FAIL);
+
+ (void) memcpy(hdr, &hbuf, dst.d_size);
+ return (ELF_READ_OKAY);
+}
+
+/*
+ * xlatetom_nhdr: There is no routine to convert Note header
+ * so we convert each field of this header.
+ */
+static int
+xlatetom_nhdr(Elf_Nhdr *nhdr)
+{
+ int r = ELF_READ_FAIL;
+
+ r |= file_xlatetom(ELF_T_WORD, (char *)&nhdr->n_namesz);
+ r |= file_xlatetom(ELF_T_WORD, (char *)&nhdr->n_descsz);
+ r |= file_xlatetom(ELF_T_WORD, (char *)&nhdr->n_type);
+ return (r);
+}
+
+/*
+ * elf_read: reads elf header, program, section headers to
+ * collect all information needed for file(1)
+ * output and stores them in Elf_Info.
+ */
+int
+elf_read(int fd, Elf_Info *EI)
+{
+ size_t size;
+ int ret = 1;
+
+ Elf_Ehdr *ehdr = &EI_Ehdr;
+
+ EI->elffd = fd;
+ size = sizeof (Elf_Ehdr);
+
+ if (pread64(EI->elffd, (void*)ehdr, size, 0) != size)
+ ret = 0;
+
+ if (file_xlatetom(ELF_T_EHDR, (char *)ehdr) == ELF_READ_FAIL)
+ ret = 0;
+
+ if (EI->file == NULL)
+ return (ELF_READ_FAIL);
+
+ EI->type = ehdr->e_type;
+ EI->machine = ehdr->e_machine;
+ EI->flags = ehdr->e_flags;
+
+ if (ret == 0) {
+ (void) fprintf(stderr, gettext("%s: %s: can't "
+ "read ELF header\n"), File, EI->file);
+ return (ELF_READ_FAIL);
+ }
+ if (process_phdr(EI) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+
+ /* We don't need section info for core files */
+ if (ehdr->e_type != ET_CORE)
+ if (process_shdr(EI) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+
+ return (ELF_READ_OKAY);
+}
+
+/*
+ * get_phdr: reads program header of specified index.
+ */
+static int
+get_phdr(Elf_Info *EI, int inx)
+{
+ off_t off = 0;
+ size_t size;
+ Elf_Ehdr *ehdr = &EI_Ehdr;
+
+ if (inx >= ehdr->e_phnum)
+ return (ELF_READ_FAIL);
+
+ size = sizeof (Elf_Phdr);
+ off = (off_t)ehdr->e_phoff + (inx * size);
+ if (pread64(EI->elffd, (void *)&EI_Phdr, size, off) != size)
+ return (ELF_READ_FAIL);
+
+ if (file_xlatetom(ELF_T_PHDR, (char *)&EI_Phdr) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+
+ return (ELF_READ_OKAY);
+}
+
+/*
+ * get_shdr: reads section header of specified index.
+ */
+static int
+get_shdr(Elf_Info *EI, int inx)
+{
+ off_t off = 0;
+ size_t size;
+ Elf_Ehdr *ehdr = &EI_Ehdr;
+
+ if (inx >= ehdr->e_shnum)
+ return (ELF_READ_FAIL);
+
+ size = sizeof (Elf_Shdr);
+ off = (off_t)ehdr->e_shoff + (inx * size);
+
+ if (pread64(EI->elffd, (void *)&EI_Shdr, size, off) != size)
+ return (ELF_READ_FAIL);
+
+ if (file_xlatetom(ELF_T_SHDR, (char *)&EI_Shdr) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+
+ return (ELF_READ_OKAY);
+}
+
+/*
+ * process_phdr: Read Program Headers and see if it is a core
+ * file of either new or (pre-restructured /proc)
+ * type, read the name of the file that dumped this
+ * core, else see if this is a dynamically linked.
+ */
+static int
+process_phdr(Elf_Info *EI)
+{
+ register int inx;
+
+ Elf_Nhdr Nhdr, *nhdr; /* note header just read */
+ Elf_Phdr *phdr = &EI_Phdr;
+
+ int class;
+ int ntype;
+ size_t nsz, nmsz, dsz;
+ off_t offset;
+ char *psinfo, *fname;
+
+ nsz = sizeof (Elf_Nhdr);
+ nhdr = &Nhdr;
+ class = get_class();
+ for (inx = 0; inx < EI_Ehdr.e_phnum; inx++) {
+ if (get_phdr(EI, inx) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+
+ /* read the note if it is a core */
+ if (phdr->p_type == PT_NOTE &&
+ EI_Ehdr.e_type == ET_CORE) {
+ /*
+ * If the next segment is also a note, use it instead.
+ */
+ if (get_phdr(EI, inx+1) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+ if (phdr->p_type != PT_NOTE) {
+ /* read the first phdr back */
+ if (get_phdr(EI, inx) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+ }
+ offset = phdr->p_offset;
+ if (pread64(EI->elffd, (void *)nhdr, nsz, offset)
+ != nsz)
+ return (ELF_READ_FAIL);
+
+ /* Translate the ELF note header */
+ if (xlatetom_nhdr(nhdr) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+
+ ntype = nhdr->n_type;
+ nmsz = nhdr->n_namesz;
+ dsz = nhdr->n_descsz;
+
+ offset += nsz + ((nmsz + 0x03) & ~0x3);
+ if ((psinfo = malloc(dsz)) == NULL) {
+ int err = errno;
+ (void) fprintf(stderr, gettext("%s: malloc "
+ "failed: %s\n"), File, strerror(err));
+ exit(1);
+ }
+ if (pread64(EI->elffd, psinfo, dsz, offset) != dsz)
+ return (ELF_READ_FAIL);
+ /*
+ * 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 (class == ELFCLASS32) {
+ /* 32-bit core file, 32-bit structures */
+ if (ntype == NT_PSINFO)
+ fname = psinfo + 88;
+ else /* old: NT_PRPSINFO */
+ fname = psinfo + 84;
+ } else if (class == ELFCLASS64) {
+ /* 64-bit core file, 64-bit structures */
+ if (ntype == NT_PSINFO)
+ fname = psinfo + 136;
+ else /* old: NT_PRPSINFO */
+ fname = psinfo + 120;
+ }
+ EI->core_type = (ntype == NT_PRPSINFO)?
+ EC_OLDCORE : EC_NEWCORE;
+ (void) memcpy(EI->fname, fname, strlen(fname));
+ free(psinfo);
+ }
+ if (phdr->p_type == PT_DYNAMIC) {
+ EI->dynamic = B_TRUE;
+ }
+ }
+ return (ELF_READ_OKAY);
+}
+
+/*
+ * process_shdr: Read Section Headers to attempt to get HW/SW
+ * capabilities by looking at the SUNW_cap
+ * section and set string in Elf_Info.
+ * Also look for symbol tables and debug
+ * information sections. Set the "stripped" field
+ * in Elf_Info with corresponding flags.
+ */
+static int
+process_shdr(Elf_Info *EI)
+{
+ int capn, mac;
+ int i, j, idx;
+ off_t cap_off;
+ size_t csize;
+ char *section_name;
+ Elf_Cap Chdr;
+ Elf_Shdr *shdr = &EI_Shdr;
+
+
+ csize = sizeof (Elf_Cap);
+ mac = EI_Ehdr.e_machine;
+
+ /* if there are no sections, return success anyway */
+ if (EI_Ehdr.e_shoff == 0 && EI_Ehdr.e_shnum == 0)
+ return (ELF_READ_OKAY);
+
+ /* read section names from String Section */
+ if (get_shdr(EI, EI_Ehdr.e_shstrndx) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+
+ if ((section_name = malloc(shdr->sh_size)) == NULL)
+ return (ELF_READ_FAIL);
+
+ if (pread64(EI->elffd, section_name, shdr->sh_size, shdr->sh_offset)
+ != shdr->sh_size)
+ return (ELF_READ_FAIL);
+
+ /* read all the sections and process them */
+ for (idx = 1, i = 0; i < EI_Ehdr.e_shnum; idx++, i++) {
+ char *str;
+
+ if (get_shdr(EI, i) == ELF_READ_FAIL)
+ return (ELF_READ_FAIL);
+
+ if (shdr->sh_type == SHT_NULL) {
+ idx--;
+ continue;
+ }
+
+ cap_off = shdr->sh_offset;
+ if (shdr->sh_type == SHT_SUNW_cap) {
+ if (shdr->sh_size == 0 || shdr->sh_entsize == 0) {
+ (void) fprintf(stderr, ELF_ERR_ELFCAP1,
+ File, EI->file);
+ return (ELF_READ_FAIL);
+ }
+ capn = (shdr->sh_size / shdr->sh_entsize);
+ for (j = 0; j < capn; j++) {
+ /*
+ * read cap and xlate the values
+ */
+ if (pread64(EI->elffd, &Chdr, csize, cap_off)
+ != csize ||
+ file_xlatetom(ELF_T_CAP, (char *)&Chdr)
+ == 0) {
+ (void) fprintf(stderr, ELF_ERR_ELFCAP2,
+ File, EI->file);
+ return (ELF_READ_FAIL);
+ }
+
+ if (Chdr.c_tag != CA_SUNW_NULL) {
+ (void) cap_val2str(Chdr.c_tag,
+ Chdr.c_un.c_val,
+ EI->cap_str,
+ sizeof (EI->cap_str),
+ 0, mac);
+ }
+ cap_off += csize;
+ }
+ }
+
+ /*
+ * 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"
+ */
+ if ((EI->stripped & E_NOSTRIP) == E_NOSTRIP)
+ continue;
+
+ if (!(EI->stripped & E_SYMTAB) &&
+ (shdr->sh_type == SHT_SYMTAB)) {
+ EI->stripped |= E_SYMTAB;
+ continue;
+ }
+
+ str = &section_name[shdr->sh_name];
+
+ if (!(EI->stripped & E_DBGINF) &&
+ ((shdr->sh_type == SHT_SUNW_DEBUG) ||
+ (shdr->sh_type == SHT_SUNW_DEBUGSTR) ||
+ (is_in_list(str)))) {
+ EI->stripped |= E_DBGINF;
+ }
+ }
+ free(section_name);
+
+ return (ELF_READ_OKAY);
+}
diff --git a/usr/src/cmd/file/elf_read.h b/usr/src/cmd/file/elf_read.h
new file mode 100644
index 0000000000..3d05464e7c
--- /dev/null
+++ b/usr/src/cmd/file/elf_read.h
@@ -0,0 +1,104 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ELF_READ_H
+#define _ELF_READ_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define BUFSZ 128
+typedef struct Elf_Info {
+ boolean_t dynamic; /* dymanically linked? */
+ unsigned core_type; /* core? what type of core? */
+ unsigned stripped; /* symtab, debug info */
+ unsigned flags; /* e_flags */
+ unsigned machine; /* e_machine */
+ unsigned type; /* e_type */
+ int elffd; /* fd of file being processed */
+ char fname[PRFNSZ]; /* name of process that dumped core */
+ char cap_str[BUFSZ]; /* hw/sw capabilities */
+ char *file; /* file being processed */
+} Elf_Info;
+
+/* values for Elf_Info.stripped */
+#define E_DBGINF 0x01
+#define E_SYMTAB 0x02
+#define E_NOSTRIP 0x03
+
+/* values for Elf_Info.core_type; */
+#define EC_NOTCORE 0x0
+#define EC_OLDCORE 0x1
+#define EC_NEWCORE 0x2
+
+/* elf file processing errors */
+#define ELF_ERR_ELFCAP1 gettext("%s: %s zero size or zero entry ELF " \
+ "section - ELF capabilities ignored\n")
+#define ELF_ERR_ELFCAP2 gettext("%s: %s: can't read ELF capabilities " \
+ "data - ELF capabilities ignored\n")
+
+extern int is_in_list(char *str);
+
+/* return status for elf_read and its helper functions */
+#define ELF_READ_OKAY 1
+#define ELF_READ_FAIL 0
+
+#if defined(_ELF64)
+
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Phdr Elf64_Phdr
+#define Elf_Cap Elf64_Cap
+#define Elf_Nhdr Elf64_Nhdr
+
+#define elf_read elf_read64
+#define elf_xlatetom elf64_xlatetom
+#define elf_fsize elf64_fsize
+#define get_class get_class64
+#define get_version get_version64
+#define get_format get_format64
+
+#else
+
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Phdr Elf32_Phdr
+#define Elf_Cap Elf32_Cap
+#define Elf_Nhdr Elf32_Nhdr
+
+#define elf_read elf_read32
+#define elf_xlatetom elf32_xlatetom
+#define elf_fsize elf32_fsize
+#define get_class get_class32
+#define get_version get_version32
+#define get_format get_format32
+
+#endif
+
+/* so lint can understand elf_read64 is defined */
+#ifdef lint
+#define elf_read64 elf_read
+#endif /* lint */
+
+#endif /* _ELF_READ_H */
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);
}
}
diff --git a/usr/src/cmd/file/req.flg b/usr/src/cmd/file/req.flg
index c041fc35c6..6dfcb7b3d7 100644
--- a/usr/src/cmd/file/req.flg
+++ b/usr/src/cmd/file/req.flg
@@ -3,9 +3,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -21,10 +20,11 @@
# CDDL HEADER END
#
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#pragma ident "%Z%%M% %I% %E% SMI"
echo_file usr/src/common/elfcap/elfcap.h
echo_file usr/src/common/elfcap/elfcap.c
+echo_file usr/src/common/sgsrtcid/sgsrtcid.h