magic(1) - file(1) in perl, BETA release 2, Part05/06 
Author Message
 magic(1) - file(1) in perl, BETA release 2, Part05/06

This is another (much-enlarged) beta release of my file(1) clone in
perl, called "magic".  Its main advantage is that it knows about many,
many types of files, and prints more informative descriptions than
file(1) does (or can).  It requires perl 4.019.

I invite comments, improvements, and particularly expansions to
recognize more types of files and classes of executables.  (It is
currently somewhat weak in the image formats section.) See the README
in the shar in Part01 for more details.

I will post the first real release (which will hopefully be better
after feedback from this release) to comp.sources.misc for archiving.


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#               "End of archive 5 (of 6)."
# Contents:  isxout.pl

PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'isxout.pl' -a "${1}" != "-c" ; then
  echo shar: Will not clobber existing file \"'isxout.pl'\"
else
echo shar: Extracting \"'isxout.pl'\" \(24668 characters\)
sed "s/^X//" >'isxout.pl' <<'END_OF_FILE'
X#-------
X# $RCSfile: isxout.pl,v $$Revision: 0.4 $$Date: 1992/01/30 18:58:27 $
X#
X# isxout.pl - recognizer for x.out files
X#
X# Additional information is printed to the standard output when
X# &IsXout() or &IsXoutRel() is true according to the settings of the
X# following variables:
X#
X# $verbose_xout                If true, a dump of the object file
X#                      header information is printed.
X#
X# $verbose_XOUT                If true, a verbose dump of the object file
X#                      header information is printed.
X#                      (All available information.)
X#
X# $Log: isxout.pl,v $
X# Revision 0.4  1992/01/30  18:58:27  dws
X# Allowed both LSB and MSB x.out files.
X# (MSB support is untested since I don't have any examples.)
X#
X# Revision 0.3  1992/01/28  02:18:32  dws
X# Added xenix magic that used to be in isbsd.pl.
X#
X# Revision 0.2  1992/01/25  05:59:39  dws
X# Added x.out executable recognition.
X#
X# Revision 0.1  1992/01/24  20:03:25  dws
X# Added x.out relocatable recognition.
X#
X# Revision 0.0  1992/01/23  20:28:08  dws
X# Initial revision.
X#
X#-------


X
X#-------
X# x.out executable format
X#
X# source: SCO xenix 2.1.1 <sys/a.out.h>

X#
X# char:                1
X# short:       2
X# int:         2
X# long:                4
X#
X# byte order:  LSB presumed, since I have seen xenix with no other
X#              byte order (not that it doesn't exist; I just haven't
X#              seen it).
X#-------
X# The main and extended header structures.
X#
X# For x.out segmented (XE_SEG):
X#     1) fields marked with (s) must contain sums of xs_psize for
X#       non-memory images, or xs_vsize for memory images.
X#     2) the contents of fields marked with (u) are undefined.
X#-------
X# For the 386 all these fields assume their full 32 bit meaning
X#
X# This is still sufficient for 386 large model so long as the sum of
X# the virtual sizes of the segments does not exceed 4Gb.
X#
X# The linker must generate some new data here, specifically:
X#
X#      x_cpu == XC_386
X#      x_renv  has new bits interpretations controlled by
X#              the -V option of the linker (see below).
X#-------
X# struct xexec {                       x.out header
X# 0:   unsigned short  x_magic;        magic number
X# 2:   unsigned short  x_ext;          size of header extension
X# 4:   long            x_text;         size of text segment (s)
X# 8:   long            x_data;         size of initialized data (s)
X# 12:  long            x_bss;          size of uninitialized data (s)
X# 16:  long            x_syms;         size of symbol table (s)
X# 20:  long            x_reloc;        relocation table length (s)
X# 24:  long            x_entry;        entry point, machine dependent
X# 28:  char            x_cpu;          cpu type & byte/word order
X# 29:  char            x_relsym;       relocation & symbol format (u)
X# 30:  unsigned short  x_renv;         run-time environment
X# };
X#-------
X# For the 386 the following fields are affected:
X#
X# xe_pagesize  set by the linker option -R this is currently 0 and
X#              should be set to the pagesize of the 386 XENIX
X#              implementation modulo 512.
X#-------
X# struct xext {                                x.out header extension
X# The following 4 fields are UNUSED currently
X# 32:  long            xe_trsize;      size of text relocation (s)
X# 36:  long            xe_drsize;      size of data relocation (s)
X# 40:  long            xe_tbase;       text relocation base (u)
X# 44:  long            xe_dbase;       data relocation base (u)
X# End of unused fields
X# 48:  long            xe_stksize;     stack size (if XE_FS set)
X# The following must be present if XE_SEG
X# 52:  long            xe_segpos;      segment table position
X# 56:  long            xe_segsize;     segment table size
X# 60:  long            xe_mdtpos;      machine dependent table position
X# 64:  long            xe_mdtsize;     machine dependent table size
X# 68:  char            xe_mdttype;     machine dependent table type
X# 69:  char            xe_pagesize;    file pagesize, in multiples of 512
X# 70:  char            xe_ostype;      operating system type
X# 71:  char            xe_osvers;      operating system version
X# 72:  unsigned short  xe_eseg;        entry segment, machine dependent
X# 74:  unsigned short  xe_sres;        reserved
X# };
X#-------
X#-------
X# Definitions for xexec.x_magic, HEX (short).
X#
X# X_MAGIC      0x0206  indicates x.out header
X#
X# 0x0602  1538 0003002 X_MAGIC_LSB     indicates x.out header
X# 0x0206   518 0001006 X_MAGIC_MSB     indicates x.out header
X#-------
X$X_MAGIC_LSB=  "\x06\x02";
X$X_MAGIC_MSB=  "\x02\x06";
X#                      indicates x.out header
X
X#-------
X# Definitions for xexec.x_cpu, cpu type (char).
X#
X#      b               set if high byte first in short
X#       w              set if low word first in long
X#        cccccc        cpu type
X#-------
X
X# bytes/words are "swapped" if not stored in pdp11 ordering
X$XC_BSWAP=     0x80;
X#                      bytes swapped
X$XC_WSWAP=     0x40;
X#                      words swapped
X$XC_CPU=       0x3f;
X#                      cpu mask
X
X%x_cpu =
X( ($XC_PDP11=  '0x01') ,'pdp11'
X, ($XC_23=     '0x02') ,'23fixed from pdp11'
X, ($XC_Z8K=    '0x03') ,'Z8000'
X, ($XC_8086=   '0x04') ,'8086'
X, ($XC_68K=    '0x05') ,'M68000'
X, ($XC_Z80=    '0x06') ,'Z80'
X, ($XC_VAX=    '0x07') ,'VAX 780/750'
X, ($XC_16032=  '0x08') ,'NS16032'
X, ($XC_286=    '0x09') ,'80286'
X, ($XC_286V=   '0x29') ,'80286'        # use xe_osver for version
X, ($XC_386=    '0x0a') ,'80386'
X, ($XC_186=    '0x0b') ,'80186'
X);
X
X
X#-------
X# Definitions for xexec.x_relsym (char), valid only if !XE_SEG.
X#
X#      rrrr            relocation table format
X#          ssss        symbol table format
X#-------
X
X# relocation table format
X#define XR_RXOUT       0x00    /* x.out long form, linkable */
X#define XR_RXEXEC      0x10    /* x.out short form, executable */
X#define XR_RBOUT       0x20    /* b.out format */
X#define XR_RAOUT       0x30    /* a.out format */
X#define XR_R86REL      0x40    /* 8086 relocatable format */
X#define XR_R86ABS      0x50    /* 8086 absolute format */
X#define XR_R286ABS     0x60    /* 80286 absolute format */
X#define XR_R286REL     0x70    /* 80286 relocatable format */
X#define XR_REL         0xf0    /* relocation format mask */
X
X# symbol table format
X#define XR_SXOUT       0x00    /* trailing string, struct sym */
X#define XR_SBOUT       0x01    /* trailing string, struct bsym */
X#define XR_SAOUT       0x02    /* struct asym (nlist) */
X#define XR_S86REL      0x03    /* 8086 relocatable format */
X#define XR_S86ABS      0x04    /* 8086 absolute format */
X#define XR_SUCBVAX     0x05    /* separate string table */
X#define XR_S286ABS     0x06    /* 80286 absolute format */
X#define XR_S286REL     0x07    /* 80286 relocatable format */
X#define XR_SXSEG       0x08    /* segmented format */
X#define XR_SYM         0x0f    /* symbol format mask */
X
X
X#-------
X# Definitions for xexec.x_renv (short).
X#
X#      vv                  version compiled for
X#        xx                extra (zero)
X#          s               set if segmented x.out
X#           a              set if absolute (set up for physical address)
X#            i             set if segment table contains iterated text/data
X#             v            set if virtual kernel module or shared library
X#                                 was (h) but this was never used.
X#              f           set if floating point hardware required
X#               t          set if large model text
X#                d         set if large model data
X#                 o        set if text overlay
X#                  f       set if fixed stack
X#                   p      set if text pure
X#                    s     set if separate I & D
X#                     e    set if executable
X#-------
X
X#-------
X# On the 386 the validity of a module and its type is determined by the
X# settings of the XE_ABS, XE_VMOD and XE_EXEC bits as follows:
X#
X#      XE_ABS  XE_VMOD XE_EXEC Meaning
X#      0       0       0       BAD x.out (error in linking)
X#      0       0       1       Old x.out, no shared libraries used.
X#      0       1       0       Shared Library Module.
X#      0       1       1       x.out executable that uses shared libs.
X#      1       0       0       BAD (not possible)
X#      1       0       1       Standalone Program (e.g. kernel)
X#      1       1       0       Virtual Kernel Module (e.g. IDD)
X#      1       1       1       BAD (not possible)
X#
X# The setting of the XE_VMOD bit is controlled by the -V option of the
X# linker.
X#-------
X
X$XE_V2=                0x4000;
X#                      version 2.x
X$XE_V3=                0x8000;
X#                      version 3.x
X$XE_V5=                0xc000;
X#                      else assume v5.x
X$XE_VERS=      0xc000;
X#                      version mask
X#                      if XE_SEG use xe_osvers ...
X
X$XE_res1=      0x2000;
X#                      reserved
X$XE_res2=      0x1000;
X#                      reserved
X$XE_SEG=       0x0800;
X#                      segment table present
X$XE_ABS=       0x0400;
X#                      absolute memory image (standalone)
X$XE_ITER=      0x0200;
X#                      iterated text/data present
X$XE_VMOD=      0x0100;
X#                      virtual module
X$XE_FPH=       0x0080;
X#                      floating point hardware required
X$XE_LTEXT=     0x0040;
X#                      large model text
X$XE_LDATA=     0x0020;
X#                      large model data
X$XE_OVER=      0x0010;
X#                      text overlay
X$XE_FS=                0x0008;
X#                      fixed stack
X$XE_PURE=      0x0004;
X#                      pure text
X$XE_SEP=       0x0002;
X#                      separate I & D
X$XE_EXEC=      0x0001;
X#                      executable
X
X#-------
X# compilation models (empirical)
X#-------
X$xe_mod_mask   = $XE_LTEXT | $XE_LDATA;
X$xe_mod_s      = 0;
X$xe_mod_m      = $XE_LTEXT;
X$xe_mod_l      = $XE_LTEXT | $XE_LDATA;
X
X#-------
X# x_renv($x_renv)
X#
X# Return a string describing the flags set in the given x_renv value.
X#-------
Xsub x_renv
X{

X       local($ans)     = '';
X       local($flag);
X
X       foreach $flag   ( 'XE_V2'
X                       , 'XE_V3'
X                       , 'XE_V5'
X                       )
X       {
X               if(($x_renv & $XE_VERS) == eval "\$$flag")
X               {
X                       $ans .= $flag . " ";
X               }
X       }
X
X       foreach $flag   ( 'XE_res1'
X                       , 'XE_res2'
X                       , 'XE_SEG'
X                       , 'XE_ABS'
X                       , 'XE_ITER'
X                       , 'XE_VMOD'
X                       , 'XE_FPH'
X                       , 'XE_LTEXT'
X                       , 'XE_LDATA'
X                       , 'XE_OVER'
X                       , 'XE_FS'
X                       , 'XE_PURE'
X                       , 'XE_SEP'
X                       , 'XE_EXEC'
X                       )
X       {
X               if($x_renv & eval "\$$flag")
X               {
X                       $ans .= $flag . " ";
X               }
X       }
X
X       # get rid of trailing space
X       chop $ans       if($ans ne '');
X
X       return $ans;
X}
X
X#-------
X# Definitions for xe_mdttype (char).
X#-------
X
X#define        XE_MDTNONE      0       /* no machine dependent table */
X#define        XE_MDT286       1       /* iAPX286 LDT */
X
X
X#-------
X# Definitions for xe_ostype (char).
X#-------
X
X#define        XE_OSNONE       0
X#define        XE_OSXENIX      1       /* Xenix */
X#define        XE_OSRMX        2       /* iRMX */
X#define        XE_OSCCPM       3       /* Concurrent CP/M */
X
X
X#-------
X# Definitions for xe_osvers (char).
X#-------
X
X#define        XE_OSXV2        0       /* Xenix V3.x */
X#define        XE_OSXV3        1       /* Xenix V3.x */
X#define        XE_OSXV5        2       /* Xenix V5.x */
X
X#-------
X# /*
X#  *   for the 386:
X#  *
X#  *   xs_filpos       set to a multiple of xe_pagesize*512 to allow
X#  *                   demand loading from the file system.
X#  *   xs_rbase        modulo xe_pagesize*512 and set using the -D and
X#  *                   -T options of the linker.
X#  */
X#
X# struct xseg {                        x.out segment table entry (32 bytes)
X# 0:   unsigned short  xs_type;        segment type
X# 2:   unsigned short  xs_attr;        segment attributes
X# 4:   unsigned short  xs_seg;         segment number
X# 6:   char            xs_align;       log base 2 of alignment
X# 7:   char            xs_cres;        unused
X# 8:   long            xs_filpos;      file position
X# 12:  long            xs_psize;       physical size (in file)
X# 16:  long            xs_vsize;       virtual size (in core)
X# 20:  long            xs_rbase;       relocation base address/offset
X# 24:  unsigned short  xs_noff;        segment name string table offset
X# 26:  unsigned short  xs_sres;        unused
X# 28:  long            xs_lres;        unused
X# };
X#-------
X
X#-------
X# Definitions for xs_type (short).
X#
X# Values from 64 to 127 are reserved.
X#-------
X
X%xs_type =
X(($XS_TNULL=   0)      ,'unused segment'
X,($XS_TTEXT=   1)      ,'text segment'
X,($XS_TDATA=   2)      ,'data segment'
X,($XS_TSYMS=   3)      ,'symbol table segment'
X,($XS_TREL=    4)      ,'relocation segment'
X,($XS_TSESTR=  5)      ,"segment table's string table segment"
X,($XS_TGRPS=   6)      ,'group definitions segment'
X,($XS_TIDATA=  64)     ,'iterated data'
X,($XS_TTSS=    65)     ,'tss'
X,($XS_TLFIX=   66)     ,'lodfix'
X,($XS_TDNAME=  67)     ,'descriptor names'
X,($XS_TDTEXT=  68)     ,'debug text segment'
X,($XS_TDFIX=   69)     ,'debug relocation'
X,($XS_TOVTAB=  70)     ,'overlay table'
X,($XS_TSYSTR=  72)     ,'symbol string table'
X);
X
X#-------
X# Definitions for xs_attr (short).
X#
X# The top bit is set if the file segment represents a memory image.
X# The low 15 bits' definitions depend on the type of file segment.
X#-------
X
X$XS_AMEM=      0x8000;
X#                      segment represents a memory image
X$XS_AMASK=     0x7fff;
X#                      type specific field mask
X
X# For XS_TTEXT and XS_TDATA segments, bit definitions.
X$XS_AITER=     0x0001;
X#                      contains iteration records
X$XS_AHUGE=     0x0002;
X#                      contains huge element
X$XS_ABSS=      0x0004;
X#                      contains implicit bss
X$XS_APURE=     0x0008;
X#                      read-only, may be shared
X$XS_AEDOWN=    0x0010;
X#                      segment expands downward (stack)
X$XS_APRIV=     0x0020;
X#                      segment may not be combined
X$XS_A32BIT=    0x0040;
X#                      segment is 32 bits
X
X# For XS_TSYMS segments, enumerated symbol table types.
X$XS_S5BELL=    0;
X#                      Bell 5.2 format
X$XS_SXSEG=     1;
X#                      x.out segmented format
X$XS_SISLAND=   2;
X#                      island de{*filter*} support
X
X# For XS_TREL segments, enumerated relocation table types.
X$XS_RXSEG=     1;
X#                      x.out segmented format
X$XS_R86SEG=    2;
X#                      8086 x.out segmented relocation
X
X#-------
X# xs_attr($xs_type, $xs_attr)
X#
X# Return a string describing the flags set in the given xs_attr value.
X#-------
Xsub xs_attr
X{

X       local($ans)     = '';
X       local($flag);
X


X
X       if($xs_type == $XS_TTEXT || $xs_type == $XS_TDATA)
X       {

X                       ,'XS_AHUGE'
X                       ,'XS_ABSS'
X                       ,'XS_APURE'
X                       ,'XS_AEDOWN'
X                       ,'XS_APRIV'
X                       ,'XS_A32BIT'
X                       );
X       }
X       elsif($xs_type == $XS_TSYMS)
X       {

X                       , 'XS_SXSEG'
X                       , 'XS_SISLAND'
X                       );
X       }
X       elsif($xs_type == $XS_TREL)
X       {

X                       , 'XS_R86SEG'
X                       );
X       }
X
X       foreach ( 'XS_AMEM'

X               )
X       {
X               if(eval "\$$_" & $xs_attr)
X               {
X                       $ans .= $_ . " ";
X               }
X       }
X

X               )
X       {
X               if(eval "\$$_" == ($xs_attr & $XS_AMASK))
X               {
X                       $ans .= $_ . " ";
X               }
X       }
X
X       # get rid of trailing space
X       chop $ans       if($ans ne '');
X
X       return $ans;
X}
X
X#-------
X# XoutSegRec - return a description of the next segment table entry.
X#
X# Uses whatever byte order currently set in $w and $W.
X#-------
Xsub XoutSegRec
X{
X       local($buf,$ans);
X       read(FILE, $buf, 32) == 32      || return '';
X
X       local   ( $xs_type
X               , $xs_attr
X               , $xs_seg
X               , $xs_align
X               , $xs_cres
X               , $xs_filpos
X               , $xs_psize
X               , $xs_vsize
X               , $xs_rbase
X               , $xs_noff
X               , $xs_sres
X               , $xs_lres) = unpack("${w}3 C2 ${W}4 ${w}2 ${W}", $buf);
X
X       $ans .= "xs_type   = $xs_type: $xs_type{$xs_type}\n";
X       $ans .= "xs_attr   = "
X               .sprintf("0x%04x", $xs_attr)
X               .": "
X               .&xs_attr($xs_type,$xs_attr)
X               ."\n";
X       $ans .= "xs_seg    = $xs_seg\n";
X#      $ans .= "xs_align  = $xs_align\n";
X#      $ans .= "xs_cres   = $xs_cres\n";
X       $ans .= "xs_filpos = $xs_filpos\n";
X       $ans .= "xs_psize  = $xs_psize\n";
X       $ans .= "xs_vsize  = $xs_vsize\n";
X#      $ans .= "xs_rbase  = $xs_rbase\n";
X#      $ans .= "xs_noff   = $xs_noff\n";
X#      $ans .= "xs_sres   = $xs_sres\n";
X#      $ans .= "xs_lres   = $xs_lres\n";
X}
X
X#-------
X# XoutSegTbl - return a description of the segment table starting at
X# the given offset and having the given size.
X#-------
Xsub XoutSegTbl # offset, size
X{

X       local($ans);
X
X       $size % 32 == 0                 || return '';
X
X       seek(FILE,$offs,0);
X       for(1 .. $size/32)
X       {
X               $ans .= &XoutSegRec;
X       }
X       $ans;
X}
X
X#-------
X# IsXout - does the current $_ buffer start an x.out file?
X# Returns a description if so, otherwise ''.
X# [The supplied $_ is presently not more than 512 bytes long.]
X#
X# This routine may assume the following variables are available:
X#
X# $path                the pathname to the file being examined
X#
X# FILE         an open file handle for the file being examined
X#
X#              No guarantees are made about the position of the file
X#              pointer; routines wishing to use this should seek()
X#              explicitly where they wish.
X#
X# $_           a buffer of at most 512 bytes read from the beginning
X#              of the file
X#-------
Xsub IsXout
X{
X       local($x_magic)         = substr($_,  0, 2);    # short
X       #-------
X       # validate magic number
X       #-------
X       return ''               if $x_magic ne $X_MAGIC_LSB
X                               && $x_magic ne $X_MAGIC_MSB;
X
X       local($ans)             = 'x.out ';
X       # unpack formats for shorts and longs
X       local($w, $W);
X
X       if ($x_magic eq $X_MAGIC_LSB)
X       {
X               $ans .= 'LSB';
X               ($w, $W)        = ('v', 'V');
X       }
X       else
X       {
X               $ans .= 'MSB';
X               ($w, $W)        = ('n', 'N');
X       }
X
X       #-------
X       # xexec variables
X       #-------
X       local($x_ext)   = unpack("x2  $w", $_);
X       local($x_text)  = unpack("x4  $W", $_);
X       local($x_data)  = unpack("x8  $W", $_);
X       local($x_bss)   = unpack("x12 $W", $_);
X       local($x_syms)  = unpack("x16 $W", $_);
X       local($x_reloc) = unpack("x20 $W", $_);
X       local($x_entry) = unpack("x24 $W", $_);
X       local($x_cpu)   = unpack("x28 C",  $_);
X       local($x_relsym)= unpack("x29 C",  $_);
X       local($x_renv)  = unpack("x30 $w", $_);
X
X       if($verbose_xout || $verbose_XOUT)
X       {
X               print "$path:\n";
X
X               print "x_ext    = $x_ext\n";
X               print "x_text   = $x_text\n";
X               print "x_data   = $x_data\n";
X               print "x_bss    = $x_bss\n";
X               print "x_syms   = $x_syms\n";
X               print "x_reloc  = $x_reloc\n";
X               print "x_entry  = $x_entry\n";
X               printf "x_cpu    = 0x%02x\n", $x_cpu;
X               printf "x_relsym = 0x%02x\n", $x_relsym;
X
X               printf "x_renv   = 0x%04x", $x_renv;
X               if($verbose_XOUT)
X               {
X                       print " == " . &x_renv($x_renv);
X               }
X               print "\n";
X       }
X
X       #-------
X       # Validate that x_cpu is as I expect.
X       # So far I have only seen LSB x.out files, so this is
X       # largely speculative.
X       #-------
X       if(($x_cpu & ~$XC_CPU) == $XC_WSWAP)
X       {
X               warn "IsXout: expected LSB x_cpu value"
X                       if $x_magic ne $X_MAGIC_LSB;
X       }
X       elsif(($x_cpu & ~$XC_CPU) == $XC_BSWAP)
X       {
X               warn "IsXout: expected MSB x_cpu value"
X                       if $x_magic ne $X_MAGIC_MSB;
X       }
X       else
X       {
X               warn "IsXout: unexpected x_cpu value";
X       }
X
X       #-------
X       # xext variables
X       #-------
X       return $ans . ' Corrupted?'     if($x_ext != 44);
X
X       local($xe_stksize)      = unpack("x48 $W", $_);
X
X       # The following must be present if XE_SEG
X       local($xe_segpos)       = unpack("x52 $W", $_);
X       local($xe_segsize)      = unpack("x56 $W", $_);
X       local($xe_mdtpos)       = unpack("x60 $W", $_);
X       local($xe_mdtsize)      = unpack("x64 $W", $_);
X       local($xe_mdttype)      = unpack("x68 C", $_);
X       local($xe_pagesize)     = unpack("x69 C", $_);
X       local($xe_ostype)       = unpack("x70 C", $_);
X       local($xe_osvers)       = unpack("x71 C", $_);
X       local($xe_eseg)         = unpack("x72 $w", $_);
X       local($xe_sres)         = unpack("x74 $w", $_);
X
X       if($verbose_xout || $verbose_XOUT)
X       {
X               print "xe_stksize  = $xe_stksize\n";
X               print "xe_segpos   = $xe_segpos\n";
X               print "xe_segsize  = $xe_segsize\n";
X               print "xe_mdtpos   = $xe_mdtpos\n";
X               print "xe_mdtsize  = $xe_mdtsize\n";
X               print "xe_mdttype  = $xe_mdttype\n";
X               print "xe_pagesize = $xe_pagesize\n";
X               print "xe_ostype   = $xe_ostype\n";
X               print "xe_osvers   = $xe_osvers\n";
X               print "xe_eseg     = $xe_eseg\n";
X               print "xe_sres     = $xe_sres\n";
X               if($verbose_XOUT && ($x_renv & $XE_SEG))
X               {
X                       print &XoutSegTbl($xe_segpos, $xe_segsize);
X               }
X       }
X
X# processortype
X       local($acpu);           # cpu type
X       local($cpu)             = sprintf("0x%02x", $x_cpu & $XC_CPU);
X
X       if(($acpu = $x_cpu{$cpu}) eq '')
X       {
X               $acpu = '(UNKNOWN CPU '.$cpu.')';
X       }
X
X       $ans .= ' ' . $acpu;
X
X# filetype
X       $ans .= ' standalone'                   if $x_renv & $XE_ABS;
X
X       local($model);          # file model
X       local($tmp)             = $x_renv & $xe_mod_mask;
X       $model  = 'small model'                 if $tmp == $xe_mod_s;
X       $model  = 'middle model'                if $tmp == $xe_mod_m;
X       $model  = 'large model'                 if $tmp == $xe_mod_l;
X       $model = '(unknown model)'              if($model eq '');
X       $ans .= ' ' . $model;
X
X       $ans .= ' segmented'                    if $x_renv & $XE_SEG;
X
X       local($file);           # file type
X       $file = 'executable'                    if $x_renv & $XE_EXEC;
X       $file = '(unknown type)'                if($file eq '');
X       $ans .= ' ' . $file;
X
X# version
X
X# otherstuff
X       $ans .= ' not stripped'         if $x_syms != 0;
X
X       return $ans;
X}
X
X#-------
X# x.out relocatable format
X#
X# source: SCO Xenix 2.2.1 <sys/relsym86.h>

X#
X# <sys/relsym86.h> - Declarations for 8086/80286 symbol
X#      table and relocation record structures.
X#
X# Combined symbol and relocation for relocatable files,
X#      (XR_R86REL | XR_S86REL).
X#
X# This format is a series of distinct records.  Each record is made up
X# of:
X#      1) 1 byte record type
X#      2) 2 byte record length (low byte first)
X#      3) record contents
X#      4) 1 byte checksum
X#
X# The record length is the number of bytes in 3 & 4.
X# When ALL of the bytes in the record are summed, the the low byte of
X# the result should be zero.
X# The record contents depend on the record type.
X# Records containing symbol names have a one byte name length followed
X# by the name itself.  The name is not terminated by a special
X# character.
X#-------
X# Some defines for record type (there are quite a few more, but these
X# are all that were present in my sample .o files.)
X#
X#define MTHEADR        0x80    module header, usually first in a rel file
X#define MCOMENT        0x88    comment record
X#define MMODEND        0x8a    module end record
X#define MEXTDEF        0x8c    external definition
X#define MPUBDEF        0x90    public definition
X#define MLNAMES        0x96    name list record
X#define MSEGDEF        0x98    segment definition
X#define MGRPDEF        0x9a    group definition
X#define MFIXUPP        0x9c    fix up previous data image
X#define MLEDATA        0xa0    logical data image
X#-------
X# Empirically, xenix relocatables begin with a single MTHEADR record
X# followed by a number of MCOMENT records.
X# The MTHEADR record contains the source filename.
X# The MCOMENT records contain strings apparently describing the
X# compiler, required libraries, memory model, and target CPU type.
X#
X# This identification is empirical, not definitive.
X#
X# In particular, the 0x9d comment record contains, in order
X#      '0'     if 8086
X# or   ''      if 80286
X#      [lms]   for large,middle,small model
X#      'O'     if optimized
X# (Is there anything else I didn't discover?)
X#
X# Example 0x9d comment records, in the form that this program dumps
X# them:
X#
X# MCOMENT \x00\x9d0l   #  8086 large  model
X# MCOMENT \x00\x9d0m   #  8086 middle model
X# MCOMENT \x00\x9d0s   #  8086 small  model
X# MCOMENT \x00\x9dl    # 80286 large  model
X# MCOMENT \x00\x9dm    # 80286 middle model
X# MCOMENT \x00\x9ds    # 80286 small  model
X#-------
X
X#-------
X# XoutRelRec - reads the next x.out relocation record from FILE,
X# returns a printable description (or '' on error).
X#-------
Xsub XoutRelRec
X{
X       local($hdr,$buf);
X
X       read(FILE, $hdr, 3) == 3        || return '';
X       local($type, $length) = unpack("C v", $hdr);
X
X       read(FILE, $buf, $length)       || return '';
X
X       #-------
X       # Make sure the sum of all the bytes is 0.
X       #-------
X       0 == unpack("%8C*", $hdr.$buf)        || return '';
X
X       #-------
X       # Get rid of the check byte and return a printable
X       # representation of this record.
X       #-------
X       chop($buf);
X       $buf =~ s/[^\x20-\x7E]/sprintf("\\x%02x",unpack("C",$&))/eg;
X
X       local($desc);
Xxrdesc:        {
X               $desc = 'MTHEADR', last xrdesc if $type == 0x80;
X               $desc = 'MCOMENT', last xrdesc if $type == 0x88;
X               $desc = 'MMODEND', last xrdesc if $type == 0x8a;
X               $desc = 'MEXTDEF', last xrdesc if $type == 0x8c;
X               $desc = 'MPUBDEF', last xrdesc if $type == 0x90;
X               $desc = 'MLNAMES', last xrdesc if $type == 0x96;
X               $desc = 'MSEGDEF', last xrdesc if $type == 0x98;
X               $desc = 'MGRPDEF', last xrdesc if $type == 0x9a;
X               $desc = 'MFIXUPP', last xrdesc if $type == 0x9c;
X               $desc = 'MLEDATA', last xrdesc if $type == 0xa0;
X
X               $desc = sprintf("0x%02x", $type);
X       }
X       sprintf("%-7s %s\n", $desc, $buf);
X}
X
X#-------
X# XoutRelHdr - returns a printable description of the initial
X# MTHEADR and MCOMENT records from FILE, which is treated as an
X# x.out relocatable file (or '' on error).
X#-------
Xsub XoutRelHdr
X{
X       local($ans, $rec);
X
X       seek(FILE,0,0);
X       $ans .= $rec    while ($rec = &XoutRelRec) ne ''
X                          && ($rec =~ /^MTHEADR/ ||
X                              $rec =~ /^MCOMENT/);
X       $ans;
X}
X
X#-------
X# XoutRelDesc - returns a printable description of all the records
X# from FILE, which is assumed to be an x.out relocatable.
X#-------
Xsub XoutRelDesc
X{
X       local($ans, $rec);
X
X       seek(FILE,0,0);
X       $ans .= $rec    while ($rec = &XoutRelRec) ne '';
X       $ans;
X}
X
X#-------
X# IsXoutRel - returns a description if the file is an x.out
X# relocatable, '' otherwise.
X#-------
Xsub IsXoutRel
X{
X       #-------
X       # Make sure the file at least begins with the appropriate
X       # byte before continuing.  This does not constitute a sure
X       # identification, but it does weed out most of the pretenders.
X       #-------
X       return ''       if substr($_, 0, 1) ne "\x80";
X
X       local($h) = &XoutRelHdr;
X       return ''       if $h eq '';
X
X       if($verbose_xout)
X       {
X               print "$path:\n";
X               print $h;
X       }
X
X       if($verbose_XOUT)
X       {
X               print "$path:\n";
X               print &XoutRelDesc;
X       }
X
X       local($*) = 1;
X
X       local($ans) = 'x.out LSB';
X
X       $ans .= ' 8086'         if $h =~ /^MCOMENT .x00.x9d0[lms].*$/;
X       $ans .= ' 80286'        if $h =~ /^MCOMENT .x00.x9d[lms].*$/;
X
X       $ans .= ' large model'  if $h =~ /^MCOMENT .x00.x9d.*l.*$/;
X       $ans .= ' middle model' if $h =~ /^MCOMENT .x00.x9d.*m.*$/;
X       $ans .= ' small model'  if $h =~ /^MCOMENT .x00.x9d.*s.*$/;
X
X       $ans .= ' optimized'    if $h =~ /^MCOMENT .x00.x9d.*O.*$/;
X
X       $ans .= ' relocatable';
X}
X#-------
X# I have NOT incorporated these due to the apparent conflict between
X# the XENIX and "STL" entries, and the offsets they use to detect
X# the compilation model.
X# What does "STL" mean here?
X# (From the Darwin magic file.)
X#
X# Mon Jan 27 20:15:34 CST 1992
X# It appears these entries are now superfluous due to the precise
X# identification done above.  They appear to have some errors, too.
X#-------
X#| #-------
X#| # XENIX executable formats: derived empirically;
X#| # treat as folklore until proven.
X#| # Assuming BSD-ish format (stripping detected at offset 16).
X#| # Since Intel machines are little-endian, it makes sense that
X#| # the longs were interpreted as shorts...
X#| #-------
X#| 0   short   0x0206  XENIX (x.out) executable
X#| >8       short   0x0001  Middle model
X#| >16      short   >0   not stripped
X#| 0   short   0x0580  XENIX 8086 relocatable or 80286 small model
X#| #-------
X#| #-------
X#| # various intel-CPU magic numbers
X#| # Assuming BSD-ish format (stripping detected at offset 16).
X#| #-------
X#| 0   short   0x0206          80286 executable (STL)
X#| >31      byte    <0x40                small model
X#| >31      byte    =0x48           large model
X#| >31      byte    =0x49           huge model
X#| >16      long    >0           not stripped
X#| #-------
END_OF_FILE
if test 24668 -ne `wc -c <'isxout.pl'`; then
    echo shar: \"'isxout.pl'\" unpacked with wrong size!
fi
# end of 'isxout.pl'
fi
echo shar: End of archive 5 \(of 6\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
        MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--



Sun, 24 Jul 1994 15:47:40 GMT  
 
 [ 1 post ] 

 Relevant Pages 

1. magic(1) - file(1) in perl, BETA release 2, Part03/06

2. magic(1) - file(1) in perl, BETA release 2, Part06/06

3. magic(1) - file(1) in perl, BETA release 2, Part01/06

4. magic(1) - file(1) in perl, BETA release 2, Part04/06

5. magic(1) - file(1) in perl, BETA release 2, Part02/06

6. magic(1) - file(1) in perl, BETA release, part04/04

7. magic(1) - file(1) in perl, BETA release, part03/04

8. magic(1) - file(1) in perl, BETA release, part02/04

9. magic(1) - file(1) in perl, BETA release, part01/04

10. Perl object database Pogo0.06 released

11. RELEASED: Data::Dumper v2.06

12. Bug in Perl 4.0 (released, not beta, version)

 

 
Powered by phpBB® Forum Software