1
0
Files
irix-657m-src/eoe/cmd/file/file.c
2022-09-29 17:59:04 +03:00

1131 lines
25 KiB
C

/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "$Revision: 1.54 $"
/* Copyright (c) 1987, 1988 Microsoft Corporation */
/* All Rights Reserved */
/* This Module contains Proprietary Information of Microsoft */
/* Corporation and should be treated as Confidential. */
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <locale.h>
#include <archives.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/attributes.h>
#include <sys/hwgraph.h>
#include <sys/mkdev.h>
#include <sys/stat.h>
#include <pfmt.h>
#include <string.h>
#include <errno.h>
#include <invent.h>
#include <paths.h>
#include <ar.h>
#include <libelf.h>
/*
** File Types
*/
#define C_TEXT 0
#define FORTRAN_TEXT 1
#define AS_TEXT 2
#define NROFF_TEXT 3
#define CMD_TEXT 4
#define ENGLISH_TEXT 5
#define ASCII_TEXT 6
#define TEXT 7
#define PS_TEXT 8
/*
** Misc
*/
#define BUFSZ 128
#define FBSZ 4096 /* justify by the fact that standard block size
* for UFS is 8K and S5 is 2K bytes
* must be >= TBLOCK, and current largest user
* is bru at 2228 bytes.
*/
#define reg register
#define NBLOCK 20
/* Assembly language comment char */
#ifdef pdp11
#define ASCOMCHAR '/'
#else
#define ASCOMCHAR '#'
#endif
char fbuf[FBSZ];
char *mfile = _PATH_MAGIC;
/* Fortran */
char *fort[] = {
"block","character","common","complex","data",
"dimension","double","entry","external","format",
"function","implicit","integer","intrinsic",
"logical","parameter","program","real","save",
"subroutine","assign","close","continue","open",
"print","read","return","rewind","stop","write",
0};
char *asc[] = {
"addiu","jal","lui","subu",0};
/* C Language */
char *c[] = {
"int","char","float","double","short","long","unsigned","register",
"static","struct","extern", 0};
/* Assembly Language */
char *as[] = {
"globl","byte","even","text","data","bss","comm",0};
char cfunc[] = { '(', ')', '{', 0 }; /* state of C function */
/* start for MB env */
wchar_t wchar;
int length;
int IS_ascii;
int Max;
/* end for MB env */
int i = 0;
int fbsz;
int ifd;
int tret;
int hflg = 0;
int Sflg = 0;
static int check_e_type(ushort);
int is_bru(void);
const char badopen[] = ":92:cannot open %s: %s\n";
#define pfmte(s,f,c,a,b) {putchar('\n'); fflush(stdout); pfmt((s),(f),(c),(a),(b));}
static void
prf(char *x)
{
if (pfmt(stdout, MM_NOSTD, "uxlibc:84:%s:\t", x) < 9)
printf("\t");
}
main(argc, argv)
int argc;
char **argv;
{
reg char *p;
reg int ch;
reg FILE *fl;
reg int cflg = 0, eflg = 0, fflg = 0;
auto char ap[BUFSZ];
extern int optind;
extern char *optarg;
(void)setlocale(LC_ALL, "");
(void)setcat("uxcore");
(void)setlabel("UX:file");
while((ch = getopt(argc, argv, "Schf:m:")) != EOF)
switch(ch) {
case 'c':
cflg++;
break;
case 'f':
fflg++;
if ((fl = fopen(optarg, "r")) == NULL) {
pfmte(stderr, MM_ERROR, badopen, optarg, strerror(errno));
goto use;
}
break;
case 'm':
mfile = optarg;
break;
case 'h':
hflg++;
break;
case 'S':
Sflg++;
break;
case '?':
eflg++;
break;
}
if(!cflg && !fflg && (eflg || optind == argc)) {
if (!eflg)
pfmt(stderr, MM_ERROR, ":194:Incorrect usage:\n");
use:
pfmt(stderr, MM_INFO,
":195:Usage: file [-S] [-c] [-h] [-f ffile] [-m mfile] file...\n");
exit(2);
}
if(mkmtab(mfile, cflg) == -1)
exit(2);
if(cflg) {
prtmtab();
exit(0);
}
for(; fflg || optind < argc; optind += !fflg) {
reg int l;
if(fflg) {
if((p = fgets(ap, BUFSZ, fl)) == NULL) {
fflg = 0;
optind--;
continue;
}
l = strlen(p);
if(l > 0)
p[l - 1] = '\0';
} else
p = argv[optind];
prf(p); /* print "file_name:<tab>" */
tret=type(p);
if(ifd)
close(ifd);
}
if (tret != 0) {
exit(tret);
} else {
exit(0); /*NOTREACHED*/
}
}
type(file)
char *file;
{
int j,nl;
int cc,tar;
char ch;
char buf[BUFSIZ];
struct stat64 mbuf;
struct stat64 statb;
int (*statf)() = hflg ? lstat64 : stat64;
int notdecl;
int cur_type;
ushort is_c_flag;
int skip_line();
int c_comment();
int c_define();
int c_function();
ifd = -1;
if ((*statf)(file, &mbuf) < 0) {
if (statf == lstat64 || lstat64(file, &mbuf) < 0) {
pfmte(stdout, MM_ERROR, badopen, file, strerror(errno));
return(0);
}
}
switch (mbuf.st_mode & S_IFMT) {
case S_IFCHR:
/* major and minor, see sys/mkdev.h */
pfmt(stdout, MM_NOSTD, ":196:character special (%d/%d)",
major(mbuf.st_rdev), minor(mbuf.st_rdev));
if (Sflg) {
int bufsize = BUFSIZ;
if (filename_to_devname(file, buf, &bufsize))
pfmt(stdout, MM_NOSTD|MM_NOGET, " --> %s", buf);
}
pfmt(stdout, MM_NOSTD|MM_NOGET,"\n");
return(0);
case S_IFDIR:
if (mbuf.st_mode&S_ISVTX)
pfmt(stdout, MM_NOSTD, "uxsgicore:2:append-only ");
pfmt(stdout, MM_NOSTD, ":197:directory\n");
return(0);
case S_IFSOCK:
pfmt(stdout, MM_NOSTD, "uxsgicore:3:socket\n");
return(0);
case S_IFIFO:
pfmt(stdout, MM_NOSTD, ":198:fifo\n");
return(0);
case S_IFNAM:
switch (mbuf.st_rdev) {
case S_INSEM:
pfmt(stdout, MM_NOSTD, ":199:Xenix semaphore\n");
return(0);
case S_INSHD:
pfmt(stdout, MM_NOSTD,
":200:Xenix shared memory handle\n");
return(0);
default:
pfmt(stdout, MM_NOSTD,
":201:unknown Xenix name special file\n");
return(0);
}
case S_IFLNK:
if ((cc = readlink(file, buf, BUFSIZ)) < 0) {
pfmte(stderr, MM_ERROR,
":202:Cannot read symbolic link %s: %s\n",
file, strerror(errno));
return(1);
}
buf[cc] = '\0';
if (stat64(file, &statb) != 0) {
pfmt(stdout, MM_NOSTD,
"uxsgicore:9:dangling symbolic link\n");
return(1);
}
pfmt(stdout, MM_NOSTD, ":203:symbolic link to %s\n", buf);
return(0);
case S_IFBLK:
/* major and minor, see sys/mkdev.h */
pfmt(stdout, MM_NOSTD, ":204:block special (%d/%d)",
major(mbuf.st_rdev), minor(mbuf.st_rdev));
if (Sflg) {
int bufsize = BUFSIZ;
if (filename_to_devname(file, buf, &bufsize))
pfmt(stdout, MM_NOSTD|MM_NOGET, " --> %s", buf);
}
pfmt(stdout, MM_NOSTD|MM_NOGET,"\n");
return(0);
}
/* check for /proc file */
if (strncmp(mbuf.st_fstype, "proc", 4) ==0) {
pfmt(stdout, MM_NOSTD,
"uxsgicore:891:/proc file, process image file\n");
return(0);
}
ifd = open(file, O_RDONLY);
if(ifd < 0) {
pfmte(stdout, MM_ERROR, badopen, file, strerror(errno));
return(0);
}
if ((fbsz = read(ifd, fbuf, FBSZ)) == -1) {
pfmte(stderr, MM_ERROR, ":205:Cannot read %s: %s\n",
file, strerror(errno));
return(1);
}
if(fbsz == 0) {
pfmt(stdout, MM_NOSTD, ":644:Empty file\n");
goto out;
}
if(fbsz >= TBLOCK) {
/* check for (new style) tar header */
union tblock *tarbuf;
tarbuf = (union tblock *)fbuf;
if ( tar = (strncmp(tarbuf->tbuf.t_magic, "ustar", 5)) == 0) {
pfmt(stdout, MM_NOSTD, ":645:tar \n");
goto out;
}
}
if(is_bru())
goto out;
if(mips_elf(ifd))
goto out;
if (script())
goto out;
/* although archives are in the Magic Table, we want to specifically
identify archives holding 32-bit and 64-bit object files */
if (object_archive())
goto out;
if(sccs()) { /* look for "1hddddd" where d is a digit */
pfmt(stdout, MM_NOSTD, ":207:sccs\n");
goto out;
}
switch(ckmtab(fbuf,fbsz,0)){ /* Check against Magic Table entries */
case -1: /* Error */
exit(2);
case 0: /* Not magic */
break;
default: /* Switch is magic index */
goto out;
}
/* look at each line for either C
* definition/declaration statement or C function.
* Skip comment, pre-processor and irrelevant lines.
* until the buffer is exhausted or C program is found.
* Avoid using goto in this C checking section.
*/
is_c_flag = i = 0; /* reset buffer index pointer and is_c_flag */
while (i < fbsz && !is_c_flag) {
switch(fbuf[i++]) {
case '/':
if(fbuf[i++] != '*')
skip_line();
else
c_comment(); /* C comment style */
continue;
case '#': /* C preprocessor, skip it */
skip_line();
continue;
case ' ':
case '\t':
skip_line();
continue;
case '\n':
continue;
default:
i--; /* back track 1 character for lookup() */
if (isalpha(fbuf[i])) {
if (lookup(c) == 1) {
if (c_define())
is_c_flag = 1;
} else {
if (c_function())
is_c_flag = 1;
} /* braces here for clarity only */
continue;
}
/* Not start with character, skip the line */
skip_line();
continue;
} /* end switch */
}
/* If is_c_flag is set, then we find C program,
* otherwise we already exhausted the buffer.
* Next step is to reset an index pointer and check
* for fortran text.
*/
if (is_c_flag) {
cur_type = C_TEXT;
goto outa;
}
notc:
i = 0;
while(fbuf[i] == 'c' || fbuf[i] == '#') {
while(fbuf[i++] != '\n')
if(i >= fbsz)
goto notfort;
}
if(lookup(fort) == 1){
cur_type = FORTRAN_TEXT;
goto outa;
}
notfort:
i = 0;
if(ascom() == 0)
goto notas;
j = i-1;
if(fbuf[i] == '.') {
i++;
if(lookup(as) == 1){
goto isas;
}
else if(j != -1 && fbuf[j] == '\n' && isalpha(fbuf[j+2])){
goto isroff;
}
}
while(lookup(asc) == 0) {
if(ascom() == 0)
goto notas;
while(fbuf[i] != '\n' && fbuf[i++] != ':')
if(i >= fbsz)
goto notas;
while(fbuf[i] == '\n' || fbuf[i] == ' ' || fbuf[i] == '\t')
if(i++ >= fbsz)
goto notas;
j = i - 1;
if(fbuf[i] == '.'){
i++;
if(lookup(as) == 1) {
goto isas;
}
else if(fbuf[j] == '\n' && isalpha(fbuf[j+2])) {
isroff: cur_type = NROFF_TEXT;
goto outa;
}
}
}
isas: cur_type = AS_TEXT;
goto outa;
notas:
/* start modification for multibyte env */
IS_ascii = 1;
if (fbsz < FBSZ)
Max = fbsz;
else
Max = FBSZ - MB_LEN_MAX; /* prevent cut of wchar read */
/* end modification for multibyte env */
for(i=0; i < Max; )
if(fbuf[i]&0200) {
IS_ascii = 0;
if (fbuf[0]=='\100' && fbuf[1]=='\357') {
pfmt(stdout, MM_NOSTD, ":209:troff output\n");
goto out;
}
/* start modification for multibyte env */
if ((length=mbtowc(&wchar, &fbuf[i],MB_LEN_MAX)) <= 0
|| !wisprint(wchar)){
pfmt(stdout, MM_NOSTD, ":208:data\n");
goto out;
}
i += length;
}
else
i++;
i = fbsz;
/* end modification for multibyte env */
if (mbuf.st_mode&(S_IXUSR|S_IXGRP|S_IXOTH))
cur_type = CMD_TEXT;
else if(english(fbuf, fbsz))
cur_type = ENGLISH_TEXT;
else if(IS_ascii)
cur_type = ASCII_TEXT;
else
cur_type = TEXT;
/* for multibyte env */
outa:
/*
* This code is to make sure that no MB char is cut in half
* while still being used.
*/
fbsz = (fbsz < FBSZ ? fbsz : fbsz - MB_CUR_MAX + 1);
while(i < fbsz){
if (isascii(fbuf[i])){
i++;
continue;
}
else {
if ((length=mbtowc(&wchar, &fbuf[i],MB_LEN_MAX)) <= 0
|| !wisprint(wchar)){
switch(cur_type){
case C_TEXT:
pfmt(stdout, MM_NOSTD,
":210:c program text with garbage\n");
break;
case FORTRAN_TEXT:
pfmt(stdout, MM_NOSTD,
":211:fortran program text with garbage\n");
break;
case AS_TEXT:
pfmt(stdout, MM_NOSTD,
":212:assembler program text with garbage\n");
break;
case NROFF_TEXT:
pfmt(stdout, MM_NOSTD,
":213:[nt]roff, tbl, or eqn input text with garbage\n");
break;
case CMD_TEXT:
pfmt(stdout, MM_NOSTD,
":214:commands text with garbage\n");
break;
case ENGLISH_TEXT:
pfmt(stdout, MM_NOSTD,
":215:English text with garbage\n");
break;
case ASCII_TEXT:
pfmt(stdout, MM_NOSTD,
":216:ascii text with garbage\n");
break;
case TEXT:
pfmt(stdout, MM_NOSTD,
":217:text with garbage\n");
break;
}
goto out;
}
i = i + length;
}
}
switch(cur_type){
case C_TEXT:
pfmt(stdout, MM_NOSTD, ":218:c program text\n");
break;
case FORTRAN_TEXT:
pfmt(stdout, MM_NOSTD, ":219:fortran program text\n");
break;
case AS_TEXT:
pfmt(stdout, MM_NOSTD, ":220:assembler program text\n");
break;
case NROFF_TEXT:
pfmt(stdout, MM_NOSTD, ":221:[nt]roff, tbl, or eqn input text\n");
break;
case CMD_TEXT:
pfmt(stdout, MM_NOSTD, ":222:commands text\n");
break;
case ENGLISH_TEXT:
pfmt(stdout, MM_NOSTD, ":223:English text\n");
break;
case ASCII_TEXT:
pfmt(stdout, MM_NOSTD, ":224:ascii text\n");
break;
case TEXT:
pfmt(stdout, MM_NOSTD, ":225:text\n");
break;
}
out:
return(0);
}
lookup(tab)
reg char **tab;
{
reg char r;
reg int k,j,l;
while(fbuf[i] == ' ' || fbuf[i] == '\t' || fbuf[i] == '\n')
i++;
for(j=0; tab[j] != 0; j++) {
l = 0;
for(k=i; ((r=tab[j][l++]) == fbuf[k] && r != '\0');k++);
if(r == '\0')
if(fbuf[k] == ' ' || fbuf[k] == '\n' || fbuf[k] == '\t'
|| fbuf[k] == '{' || fbuf[k] == '/') {
i=k;
return(1);
}
}
return(0);
}
/*
* Non-recursive check routine for C comment
* If it fails return 0, otherwise return 1
* Use global variable i and fbuf[]
*/
int
c_comment()
{
reg char cc;
while(fbuf[i] != '*' || fbuf[i+1] != '/') {
if(fbuf[i] == '\\')
i += 2;
else
i++;
if(i >= fbsz)
return(0);
}
if((i += 2) >= fbsz)
return(0);
return(1);
}
/*
* Skip the whole line in fbuf[], also
* update global index (i).
* Return 0 if go over limit, otherwise return 1
*/
int
skip_line()
{
while (fbuf[i++] != '\n') {
if (i >= fbsz )
return(0);
}
return(1);
}
/*
* Check if the line is likely to be a
* C definition/declaration statement
* If true return 1, otherwise return 0
*/
int
c_define()
{
reg char a_char;
while ((a_char = fbuf[i++]) != ';' && a_char != '{' ) {
if (i >= fbsz || a_char == '\n')
return(0);
}
return(1);
}
/*
* Check if this line and the following lines
* form a C function, normally in the format of
* func_name(....) {
* Also detect a line that can't possible be a
* C function, i.e. page_t xxx; or STATIC ino_t y();
* Update global array index (i)
* If true return 1, otherwise return 0
*/
int
c_function()
{
reg int state = 0;
while (cfunc[state] != 0) {
if (fbuf[i++] == cfunc[state]) {
if (state == 1 && (fbuf[i] == ';' || fbuf[i] == ','))
return(0);
state++;
}
if ((state == 0 && (fbuf[i] == ';' || fbuf[i] == '\n'))
|| (i >= fbsz))
return(0);
}
return(1);
}
ascom()
{
while(fbuf[i] == ASCOMCHAR || (fbuf[i] == '/' && fbuf[i+1] == '*')) {/*}*/
if ( fbuf[i] == '/' ) {
c_comment();
continue;
}
i++;
while(fbuf[i++] != '\n')
if(i >= fbsz)
return(0);
while(fbuf[i] == '\n')
if(i++ >= fbsz)
return(0);
}
return(1);
}
sccs()
{ /* look for "1hddddd" where d is a digit */
reg int j;
if(fbuf[0] == 1 && fbuf[1] == 'h') {
for(j=2; j<=6; j++) {
if(isdigit(fbuf[j]))
continue;
else
return(0);
}
} else {
return(0);
}
return(1);
}
english (bp, n)
char *bp;
int n;
{
# define NASC 128 /* number of ascii char ?? */
reg int j, vow, freq, rare;
reg int badpun = 0, punct = 0;
auto int ct[NASC];
if (n<50)
return(0); /* no point in statistics on squibs */
for(j=0; j<NASC; j++)
ct[j]=0;
for(j=0; j<n; j++)
{
if (bp[j]<NASC)
ct[bp[j]|040]++;
switch (bp[j])
{
case '.':
case ',':
case ')':
case '%':
case ';':
case ':':
case '?':
punct++;
if(j < n-1 && bp[j+1] != ' ' && bp[j+1] != '\n')
badpun++;
}
}
if (badpun*5 > punct)
return(0);
vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u'];
freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n'];
rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z'];
if(2*ct[';'] > ct['e'])
return(0);
if((ct['>']+ct['<']+ct['/'])>ct['e'])
return(0); /* shell file test */
return (vow*5 >= n-ct[' '] && freq >= 10*rare);
}
script() /* Also prints script type */
{
reg int i;
char *shellname;
if (fbuf[0] == '#' && fbuf[1] == '!') {
i = 2;
while (fbuf[i] != '\n' && fbuf[i] != '\0' && i < fbsz) {
i++;
}
if(i >= fbsz)
return 0;
pfmt(stdout, MM_NOSTD, "uxsgicore:60:%.*s script text\n", i - 2,
&fbuf[2]);
return 1;
}
return 0;
}
#include <elf.h>
#define TRUE 1
#define FALSE 0
#ifndef EF_MIPS_ARCH_3
#define EF_MIPS_ARCH_3 0x20000000
#endif
/*
* The variable for STRING_TBLE ... i
* H = elfhdr
* S = elfshdr
*/
char *name = 0;
#define STRING_TBLE(H,S) \
(name = elf_strptr(elf, H->e_shstrndx, (size_t)S->sh_name)) && \
(strncmp(name,MIPS_DEBUG_INFO,strlen(name)) == 0)
static char * e_type_str[] =
{
"uxsgicore:137: unknown type",
"uxsgicore:138: relocatable",
"uxsgicore:139: executable",
"uxsgicore:140: dynamic lib",
"uxsgicore:141: core file"
};
int
mips_elf(int fd)
{
Elf32_Ehdr *elfhdr;
elfhdr = (Elf32_Ehdr *) fbuf;
if (!IS_ELF(*elfhdr) || elfhdr->e_machine != EM_MIPS)
return 0;
switch (elfhdr->e_ident[EI_CLASS]) {
case ELFCLASSNONE:
return mips_elfnone(fd);
case ELFCLASS32:
return mips_elf32(fd);
case ELFCLASS64:
return mips_elf64(fd);
default:
break;
}
return 0;
}
int
mips_elfnone(int fd)
{
Elf32_Ehdr *elfhdr;
Elf32_Shdr elfshdr;
int n;
elfhdr = (Elf32_Ehdr *) fbuf;
printf("ELF");
/* It is ELFCLASSNONE */
if (elfhdr->e_ident[EI_DATA] == ELFDATA2LSB)
pfmt(stdout, MM_NOSTD, "uxsgicore:143: LSB");
if (elfhdr->e_ident[EI_DATA] == ELFDATA2MSB)
pfmt(stdout, MM_NOSTD, "uxsgicore:144: MSB");
if (check_e_type(elfhdr->e_type))
return 0;
pfmt(stdout, MM_NOSTD, "uxsgicore:146: MIPS");
pfmt(stdout, MM_NOSTD, "uxsgicore:147: - version %ld\n", elfhdr->e_version);
return 1;
}
int
mips_elf32(int fd)
{
Elf *elf;
Elf_Cmd cmd;
Elf_Scn *scn;
Elf32_Ehdr *elfhdr;
Elf32_Shdr *elfshdr;
int dynamic = FALSE;
int stripped= TRUE;
Elf32_Word arch;
int n;
scn=0;
cmd = ELF_C_READ;
if(elf_version(EV_CURRENT) == EV_NONE) {
pfmt(stdout, MM_NOSTD, "uxsgicore:946: Using old version of libelf.");
return (1);
}
if((elf = elf_begin(fd, cmd, (Elf *)0)) == NULL) {
pfmt(stdout, MM_NOSTD,
"uxsgicore:947: Error from file command using elf_begin routine.");
elf_end(elf);
return (1);
}
if ((elfhdr = elf32_getehdr(elf)) == NULL) {
pfmt(stdout, MM_NOSTD,
"uxsgicore:948: Error from file command using elf_getehdr routine.\n");
elf_end(elf);
return (1);
}
while ((scn = elf_nextscn(elf, scn)) != 0) {
if ((elfshdr = elf32_getshdr(scn)) != 0) {
if (elfshdr->sh_type == SHT_DYNAMIC)
dynamic = TRUE;
/* if it's n32 and has a dwarf or it's o32 and has an mdebug
* symbol table, it's not stripped */
if(elfhdr->e_flags & EF_MIPS_ABI2) { /* n32 */
if(elfshdr->sh_type == SHT_MIPS_DWARF &&
STRING_TBLE(elfhdr,elfshdr))
stripped = FALSE;
}
else /* o32 */ if((name = elf_strptr(elf, elfhdr->e_shstrndx,
(size_t)elfshdr->sh_name)) &&
strncmp(name,MIPS_MDEBUG,strlen(name)) == 0)
stripped = FALSE;
}
}
printf("ELF");
/* It is ELFCLASS32 */
if (elfhdr->e_flags & EF_MIPS_ABI2)
pfmt(stdout, MM_NOSTD, "uxsgicore:945: N32");
else
pfmt(stdout, MM_NOSTD, "uxsgicore:142: 32-bit");
if (elfhdr->e_ident[EI_DATA] == ELFDATA2LSB)
pfmt(stdout, MM_NOSTD, "uxsgicore:143: LSB");
if (elfhdr->e_ident[EI_DATA] == ELFDATA2MSB)
pfmt(stdout, MM_NOSTD, "uxsgicore:144: MSB");
if (arch=elfhdr->e_flags & EF_MIPS_ARCH) {
if (arch == EF_MIPS_ARCH_2)
pfmt(stdout, MM_NOSTD, "uxsgicore:135: mips-2");
else if (arch == EF_MIPS_ARCH_3)
pfmt(stdout, MM_NOSTD, "uxsgicore:136: mips-3");
else if (arch == EF_MIPS_ARCH_4)
pfmt(stdout, MM_NOSTD, "uxsgicore:942: mips-4");
}
if (dynamic && elfhdr->e_type==ET_EXEC)
pfmt(stdout, MM_NOSTD, "uxsgicore:133: dynamic");
if (check_e_type(elfhdr->e_type)) {
elf_end(elf);
return 0;
}
if (!stripped && (elfhdr->e_type==ET_REL || elfhdr->e_type==ET_EXEC))
pfmt(stdout, MM_NOSTD, "uxsgicore:145: (not stripped)");
pfmt(stdout, MM_NOSTD, "uxsgicore:146: MIPS");
pfmt(stdout, MM_NOSTD, "uxsgicore:147: - version %ld\n", elfhdr->e_version);
elf_end(elf);
return 1;
}
int
mips_elf64(int fd)
{
Elf *elf;
Elf_Cmd cmd;
Elf_Scn *scn;
Elf64_Ehdr *elfhdr;
Elf64_Shdr *elfshdr;
int dynamic = FALSE;
int stripped= TRUE;
Elf64_Word arch;
int n;
scn=0;
cmd = ELF_C_READ;
if(elf_version(EV_CURRENT) == EV_NONE) {
pfmt(stdout, MM_NOSTD, "uxsgicore:946: Using old version of libelf.");
return (1);
}
if((elf = elf_begin(fd, cmd, (Elf *)0)) == NULL) {
pfmt(stdout, MM_NOSTD,
"uxsgicore:947: Error from file command using elf_begin routine.");
elf_end(elf);
return (1);
}
if ((elfhdr = elf64_getehdr(elf)) == NULL) {
pfmt(stdout, MM_NOSTD,
"uxsgicore:948: Error from file command using elf_getehdr routine.");
elf_end(elf);
return (1);
}
while ((scn = elf_nextscn(elf, scn)) != 0) {
if ((elfshdr = elf64_getshdr(scn)) != 0) {
if (elfshdr->sh_type == SHT_DYNAMIC)
dynamic = TRUE;
if (elfshdr->sh_type == SHT_MIPS_DWARF &&
STRING_TBLE(elfhdr,elfshdr))
stripped = FALSE;
}
}
printf("ELF");
/* It is ELFCLASS64 */
/*
* If the type is ET_IR the check the flags for :
* EF_MIPS_64BIT_WHIRL = 64bit binary
* !EF_MIPS_64BIT_WHIRL = N32 binary
*
* NOTE : that the class type is set for 64bits for objects
* with ET_IR set.
*/
if(elfhdr->e_type == ET_IR) {
if (elfhdr->e_flags & EF_MIPS_64BIT_WHIRL)
pfmt(stdout, MM_NOSTD, "uxsgicore:134: 64-bit");
else
pfmt(stdout, MM_NOSTD, "uxsgicore:945: N32");
} else {
if (elfhdr->e_flags & EF_MIPS_ABI2)
pfmt(stdout, MM_NOSTD, "uxsgicore:945: N32");
else
pfmt(stdout, MM_NOSTD, "uxsgicore:134: 64-bit");
}
if (elfhdr->e_ident[EI_DATA] == ELFDATA2LSB)
pfmt(stdout, MM_NOSTD, "uxsgicore:143: LSB");
if (elfhdr->e_ident[EI_DATA] == ELFDATA2MSB)
pfmt(stdout, MM_NOSTD, "uxsgicore:144: MSB");
if (arch=elfhdr->e_flags & EF_MIPS_ARCH) {
if (arch == EF_MIPS_ARCH_2)
pfmt(stdout, MM_NOSTD, "uxsgicore:135: mips-2");
else if (arch == EF_MIPS_ARCH_3)
pfmt(stdout, MM_NOSTD, "uxsgicore:136: mips-3");
else if (arch == EF_MIPS_ARCH_4)
pfmt(stdout, MM_NOSTD, "uxsgicore:942: mips-4");
}
if (dynamic && elfhdr->e_type==ET_EXEC)
pfmt(stdout, MM_NOSTD, "uxsgicore:133: dynamic");
if (check_e_type(elfhdr->e_type)) {
elf_end(elf);
return 0;
}
if (!stripped && (elfhdr->e_type==ET_REL || elfhdr->e_type==ET_EXEC))
pfmt(stdout, MM_NOSTD, "uxsgicore:145: (not stripped)");
pfmt(stdout, MM_NOSTD, "uxsgicore:146: MIPS");
pfmt(stdout, MM_NOSTD, "uxsgicore:147: - version %ld\n", elfhdr->e_version);
elf_end(elf);
return 1;
}
static int
check_e_type(ushort elf_e_type)
{
int ret_val = 0;
switch (elf_e_type) {
case ET_NONE :
case ET_REL :
case ET_EXEC :
case ET_DYN :
case ET_CORE :
pfmt(stdout, MM_NOSTD, e_type_str[elf_e_type]);
break;
case ET_IR :
pfmt(stdout, MM_NOSTD, "uxsgicore:941: intermediate object");
break;
/*
* At this time if the ET_HIPROC bits are set then claim that
* the file has "No file type".
*/
case ET_HIPROC :
pfmt(stdout, MM_NOSTD, e_type_str[0]);
break;
default :
ret_val = 1;
break;
}
return ret_val;
}
#define BLANKS " "
int
object_archive()
{
struct ar_hdr *hdr;
if(fbsz < (SARMAG+sizeof(hdr)))
return 0;
/* see if first 8 bytes are "!<arch>\n" */
if (strncmp(fbuf, ARMAG, SARMAG))
return 0;
/* we now know the file is an archive; now we check to see if it
contains objects - if so, print it out; otherwise, return fail */
hdr = (struct ar_hdr *)&fbuf[SARMAG];
if (!strncmp(hdr->ar_name, ELF_AR64_SYMTAB_NAME,
ELF_AR64_SYMTAB_NAME_LEN) &&
!strncmp(&hdr->ar_name[ELF_AR64_SYMTAB_NAME_LEN], BLANKS,
16 - ELF_AR64_SYMTAB_NAME_LEN))
printf("current ar archive containing 64-bit objects\n");
else if (!strncmp(hdr->ar_name, ELF_AR_SYMTAB_NAME,
ELF_AR_SYMTAB_NAME_LEN) &&
!strncmp(&hdr->ar_name[ELF_AR_SYMTAB_NAME_LEN], BLANKS,
16 - ELF_AR_SYMTAB_NAME_LEN))
printf("current ar archive containing 32-bit objects\n");
else
return(0);
return(1);
}
is_bru(void)
{
/* A_MAGIC at 176, and H_MAGIC at 2224, and "SGI Release" at 400;
* allow that to not be there, in case they use 3rd party bru.
*/
/* protect against somebody dropping FBSZ */
if(FBSZ < 2228) printf("error, FBSZ too small\n");
if(fbsz>=2228 && strncmp("1234", &fbuf[176], 4) == 0 &&
strncmp("2345", &fbuf[2224], 4) == 0) {
char *notsgi;
if(strncmp("SGI Release", &fbuf[400], 11) == 0)
notsgi = "";
else
notsgi = "non-SGI ";
pfmt(stdout, MM_NOSTD, ":749:%sbru archive\n", notsgi);
return 1;
}
return 0;
}