/* 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* ** 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:" */ 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 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 #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 "!\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; }