home *** CD-ROM | disk | FTP | other *** search
/ M.u.C.S. Disc 2000 / MUCS2000.iso / gnuc / util-41s.lzh / util-41 / strip.c < prev    next >
C/C++ Source or Header  |  1998-09-12  |  18KB  |  766 lines

  1. /*
  2.  *    strip TOS executable format files of symbol table info
  3.  *    usage: strip {-g | -k | -l names} [-t] files ...
  4.  *
  5.  *    Original version by ++jrb    bammi@dsrgsun.ces.cwru.edu
  6.  *    (i.e. Jwahar Bammi)
  7.  *    Modified to add extra options -g -k and -l by
  8.  *    Michal Jaegermann        ntomczak@ualtavm.bitnet
  9.  *    November 1st, 1990
  10.  *
  11.  *    -g    keep all global symbols
  12.  *    -k    keep _stksize symbol, so stack size can be adjusted
  13.  *        even for nearly-stripped gcc produced executables
  14.  *    -l nms    keep all symbols listed in a file 'nms'
  15.  *    -t    remove additional data from end of file
  16.  *
  17.  *    Modified sources compile both with gcc and Sozobon C
  18.  *
  19.  *      Added code to deal correctly with extended symbols produced
  20.  *      by -G option of gcc
  21.  *      Both -k and -l options convert extended symbols into
  22.  *      regular ones.
  23.  *
  24.  *    ++jrb 4/25/91: 
  25.  *    Macroized the code to take care of WORD_ALIGNED cross environments.
  26.  *    Minor fixes for a !atari !gcc compiler.   
  27.  *
  28.  *    AL 08/02/92:        (alexlehm@iti.informatik.th-darmstadt.de)
  29.  *    Added -t option to strip TurboC / PureC style executables
  30.  *    Support for little endian (BYTE_SWAPed) machines
  31.  */
  32.  
  33. #include <stdio.h>
  34. #ifdef atarist
  35. #include <stat.h>
  36. #ifdef __GNUC__
  37. #  include <stddef.h>
  38. #  include <memory.h>
  39. #  include <unistd.h>
  40. #else
  41. #include <malloc.h>
  42. extern long lread();
  43. extern long lwrite();
  44. extern long lseek();
  45. #endif
  46. #endif
  47.  
  48. #ifdef unix
  49. #  include <sys/stat.h>
  50. #  include <strings.h>
  51. #  define lwrite write
  52. #  define lread  read
  53.    extern char *malloc(), *realloc();
  54. #ifdef linux
  55. #include <linux/stddef.h>
  56. #endif
  57. #else
  58. #  include <string.h>
  59. #  define lwrite _write
  60. #  define lread _read
  61. #endif
  62.  
  63. #include <fcntl.h>
  64.  
  65. #define NEWBUFSIZ    16384L
  66.  
  67. char            mybuf[NEWBUFSIZ];
  68. char            tmpname[128];
  69.  
  70. #define SYMLEN 8
  71. #define GST_SYMLEN 22
  72.  
  73. typedef char    symstr_t[GST_SYMLEN];
  74. symstr_t        stklist[] = {"__stksize", "__initial_stack"};
  75.  
  76. #ifndef __PROTO
  77. #  if __STDC__ || __cplusplus
  78. #   define __PROTO(s) s
  79. #  else
  80. #   define __PROTO(s) ()
  81. #  endif
  82. #endif
  83.  
  84. /* function pointer type for the select functions */
  85. typedef long (*select_fp) __PROTO((int, int, long, symstr_t *));
  86.  
  87. void usage __PROTO((char *s ));
  88. int main __PROTO((int argc , char **argv ));
  89. int strip __PROTO((char *name,symstr_t *nmlist,select_fp select,int cuttrail));
  90. long copy __PROTO((int from , int to , long bytes ));
  91. long copy_relo __PROTO((char *name,int from,int to));
  92. void report __PROTO((char *s ));
  93. symstr_t *mklist __PROTO((char *fname ));
  94. long sel_globs __PROTO((int fd , int tfd , long sbytes , symstr_t *nmlist ));
  95. long sel_listed __PROTO((int fd , int tfd , long sbytes , symstr_t *nmlist ));
  96. extern char    *getenv __PROTO((const char *));
  97.  
  98. extern void dump_version(char *prog);
  99. char *progname = "strip";
  100.  
  101. int 
  102. main (argc, argv)
  103.     int             argc;
  104.     char          **argv;
  105. {
  106.     int             status = 0;
  107.     int             flag = -1;
  108.     int             cuttrail = 0;
  109.     symstr_t       *nmlist = stklist;
  110.     select_fp       select = sel_listed;
  111. #ifdef atarist
  112.     char           *tmpdir;
  113.     register int    l;
  114. #endif
  115.  
  116.    if (argv[0][0] != '\0')
  117.        progname = argv[0];
  118.  
  119.     /* process arguments */
  120.     while (argv++, --argc) {
  121.     if ('-' != **argv)
  122.         break;
  123.     (*argv)++;
  124.     if( **argv=='t' ) {
  125.         cuttrail = 1;
  126.     } else {
  127.         if ((-1) != flag)
  128.         usage ("only one option at a time is accepted\n");
  129.         flag = **argv;
  130.         switch (flag) {
  131.         case 'g':
  132.             select = sel_globs;
  133.         break;
  134.         case 'k':
  135.             nmlist = stklist;
  136.         select = sel_listed;
  137.         break;
  138.         case 'a':
  139.         select = 0;
  140.         break;
  141.         case 'l':
  142.         (*argv)++;
  143.         if ('\0' == **argv) {
  144.             --argc;
  145.             argv++;
  146.             if( argc==0 )
  147.                 usage("missing names file\n");
  148.         }
  149.         if ((symstr_t *) NULL == (nmlist = mklist (*argv)))
  150.             usage ("cannot create a list of reserved names\n");
  151.         select = sel_listed;
  152.         break;
  153.        case 'v':
  154.             dump_version(progname);
  155.             exit(0);
  156.             break;
  157.         default:
  158.         usage ("");
  159.         break;
  160.         }
  161.     }
  162.     }
  163.  
  164.     if (argc < 1) {
  165.     usage ("");
  166.     }
  167.  
  168. #ifdef __GNUC__
  169. #ifdef atarist
  170.     if ((tmpdir = getenv ("TEMP")) != NULL) {
  171.     strcpy (tmpname, tmpdir);
  172.     l = (int) strlen (tmpname) - 1;
  173.     if (tmpname[l] == '\\' || tmpname[l] == '/')
  174.         tmpname[l] = '\0';
  175.     strcat (tmpname, "/STXXXXXX");
  176.     }
  177.     else
  178. #endif
  179.     strcpy (tmpname, "/tmp/STXXXXXX");
  180.  
  181.     mktemp (tmpname);
  182. #else /* not __GNUC__ */
  183. #  ifdef atarist
  184.     if ((tmpdir = getenv ("TEMP")) != NULL) {
  185.     strcpy (tmpname, tmpdir);
  186.     l = (int) strlen (tmpname) - 1;
  187.     if (tmpname[l] != '\\') {
  188.         l++;
  189.         tmpname[l] = '\\';
  190.     }
  191.     l++;
  192.     }
  193.     else {
  194.     l = 0;
  195.     }
  196.     tmpnam (&tmpname[l]);
  197. #  else
  198.     strcpy (tmpname, "/tmp/STXXXXXX");
  199.     mktemp(tmpname);
  200. #  endif    
  201. #endif /* __GNUC__ */
  202.     do {
  203.     status |= strip (*argv++, nmlist, select, cuttrail);
  204.     } while (--argc > 0);
  205.  
  206.     unlink (tmpname);
  207.     return status;
  208. }
  209.  
  210. void
  211. usage (s)
  212.     char           *s;
  213. {
  214.     report (s);
  215.     report ("Usage: strip {-k | -l names | -g | -a} [-t] files ...\n");
  216.     exit (1);
  217. }
  218.  
  219. /* define macro for big and function for little endian machines */
  220. #ifdef BYTE_SWAP
  221. short swap_short __PROTO((short s));
  222. long swap_long __PROTO((long l));
  223. #else
  224. #define swap_short(s) (s)
  225. #define swap_long(l) (l)
  226. #endif
  227.  
  228. #if (defined(__GNUC__)) && (!defined(unix))
  229. #include <st-out.h>
  230. #else
  231. /* include relevant fragments of <st-out.h> file directly */
  232.  
  233. struct aexec {
  234.      short    a_magic;    /* magic number */
  235. unsigned long    a_text;        /* size of text segment */
  236. unsigned long    a_data;        /* size of initialized data */
  237. unsigned long    a_bss;        /* size of uninitialized data */
  238. unsigned long    a_syms;        /* size of symbol table */
  239. unsigned long    a_AZero1;    /* always zero */
  240. unsigned long    a_AZero2;    /* always zero */
  241. unsigned short    a_isreloc;    /* is reloc info present */
  242. };
  243. #define    CMAGIC    0x601A        /* contiguous text */
  244.  
  245. /*
  246.  * Format of a symbol table entry
  247.  */
  248. struct    asym 
  249.     {
  250.     char        a_name[SYMLEN];    /* symbol name */
  251.     unsigned short    a_type;        /* type flag   */
  252.     unsigned long    a_value;    /* value of this symbol
  253.                        (or sdb offset) */
  254.     };
  255.  
  256. #define A_GLOBL    0x2000        /* global */
  257. #define A_LNAM  0x0048        /* extended name */
  258.  
  259. #endif /* __GNUC__ */
  260.  
  261. #if !__STDC__ && !__cplusplus
  262. #  ifndef offsetof
  263. #    define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0L)->MEMBER)
  264. #  endif
  265. #  ifndef CROSSHPUX
  266.      typedef unsigned long size_t;
  267. #  endif
  268. #endif
  269.  
  270. #ifdef WORD_ALIGNED
  271. # define SIZEOF_AEXEC ((2*sizeof(short)) + (6*sizeof(long)))
  272. # define SIZEOF_ASYM  ((SYMLEN*sizeof(char)) + sizeof(short) + sizeof(long))
  273. # define SYM_OFFSET   (sizeof(short) + (3*sizeof(long)))
  274.   int read_head __PROTO((int fd, struct aexec *a));
  275. #else
  276. # define SIZEOF_AEXEC (sizeof(struct aexec))
  277. # define SIZEOF_ASYM  (sizeof(struct asym))
  278. # define SYM_OFFSET   (offsetof (struct aexec, a_syms))
  279. #endif
  280.  
  281. int 
  282. strip (name, nmlist, select, cuttrail)
  283. char *name;
  284. symstr_t * nmlist;
  285. select_fp select;
  286. int cuttrail;
  287. {
  288.     register int    fd;
  289.     register int    tfd;
  290.     register long   count, rbytes, sbytes;
  291.     long            lbytes, swap_lbytes;
  292.     struct aexec    ahead;
  293.     struct stat        statb;
  294.  
  295.     if ((fd = open (name, O_RDONLY, 0666)) < 0) {
  296.     perror (name);
  297.     return 2;
  298.     }
  299.     if ((tfd = open (tmpname, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
  300.     perror (tmpname);
  301.     close (fd);
  302.     return 4;
  303.     }
  304. #ifndef WORD_ALIGNED
  305.     if ((count = lread (fd, &ahead, (long) sizeof (ahead))) 
  306.                     != (long) sizeof (ahead)) {
  307. #else
  308.     if (read_head (fd, &ahead)) {
  309. #endif
  310.     perror (name);
  311.     close (tfd);
  312.     close (fd);
  313.     return 8;
  314.     }
  315.     if (swap_short(ahead.a_magic)!=CMAGIC) {
  316.     report (name);
  317.     report (": Bad Magic number\n");
  318.     close (tfd);
  319.     close (fd);
  320.     return 0x10;
  321.     }
  322.     sbytes = swap_long(ahead.a_syms);
  323.     if (0L == sbytes && !cuttrail) {
  324.     report (name);
  325.     report (": Already Stripped\n");
  326.     close (tfd);
  327.     close (fd);
  328.     return 0x20;
  329.     }
  330.     if (lseek (fd, 0L, 0) < 0) {
  331.     report (name);
  332.     report (": seek error\n");
  333.     close (tfd);
  334.     close (fd);
  335.     return 0x40;
  336.     }
  337.     count = SIZEOF_AEXEC + swap_long(ahead.a_text) + swap_long(ahead.a_data);
  338.     if (copy (fd, tfd, count) != count) {
  339.     close (tfd);
  340.     close (fd);
  341.     return 0x80;
  342.     }
  343.     if (NULL == select) {     /* remove whole symbol table */
  344.     lbytes = 0L;
  345.     if (lseek (fd, sbytes, 1) < 0) {
  346.         report (name);
  347.         report (": seek error\n");
  348.         close (tfd);
  349.         close (fd);
  350.         return 0x100;
  351.     }
  352.     }
  353.     else {
  354.     lbytes = ( *select )(fd, tfd, sbytes, nmlist);
  355.     }
  356.     if( cuttrail ) {
  357.     if((rbytes = copy_relo(name,fd,tfd))<0) {
  358.          close(tfd);
  359.          close(fd);
  360.          return 0x8000;
  361.     }
  362.  
  363.     if( lread( fd, &cuttrail, 1 )!=1 ) {
  364.         report (name);
  365.         report (": Already Stripped\n");
  366.         close (tfd);
  367.         close (fd);
  368.         return 0x20;
  369.     }
  370.     } else {
  371.     if ((rbytes = copy (fd, tfd, 0x7fffffffL)) < 0) {
  372.         close (tfd);
  373.         close (fd);
  374.         return 0x200;
  375.     }
  376.     }
  377.     if (lseek (tfd, (long)(SYM_OFFSET), 0) < 0) {
  378.     close (tfd);
  379.     close (fd);
  380.     return 0x400;
  381.     }
  382.     swap_lbytes=swap_long(lbytes);
  383.     if (lwrite (tfd, &swap_lbytes, (long)sizeof (lbytes)) != 
  384.                             (long) sizeof (lbytes)) {
  385.     close (tfd);
  386.     close (fd);
  387.     return 0x800;
  388.     }
  389.     close (tfd);
  390.     close (fd);
  391.     if (stat (name, &statb) < 0)
  392.       statb.st_mode = 0666;
  393.     if (rename(tmpname, name) == 0) return 0; /* try to rename it */
  394.     if ((fd = open (name, O_WRONLY | O_TRUNC | O_CREAT, statb.st_mode)) < 0) {
  395.     perror (name);
  396.     return 0x1000;
  397.     }
  398.     if ((tfd = open (tmpname, O_RDONLY, 0666)) < 0) {
  399.     perror (tmpname);
  400.     close (fd);
  401.     return 0x2000;
  402.     }
  403.  
  404.     count = SIZEOF_AEXEC + swap_long(ahead.a_text) + swap_long(ahead.a_data) + rbytes + lbytes;
  405.     if (copy (tfd, fd, count) != count) {
  406.     close (tfd);
  407.     close (fd);
  408.     return 0x4000;
  409.     }
  410.     close (tfd);
  411.     close (fd);
  412.     return 0;
  413. }
  414.  
  415. /*
  416.  * copy from, to in NEWBUFSIZ chunks upto bytes or EOF whichever occurs first
  417.  * returns # of bytes copied
  418.  */
  419. long 
  420. copy (from, to, bytes)
  421. int from, to;
  422. long bytes;
  423. {
  424.     register long   todo, done = 0L, remaining = bytes, actual;
  425.  
  426.     while (done != bytes) {
  427.     todo = (remaining > NEWBUFSIZ) ? NEWBUFSIZ : remaining;
  428.     if ((actual = lread (from, mybuf, todo)) != todo) {
  429.         if (actual < 0) {
  430.         report ("Error Reading\n");
  431.         return -done;
  432.         }
  433.     }
  434.     if (lwrite (to, mybuf, actual) != actual) {
  435.         report ("Error Writing\n");
  436.         return -done;
  437.     }
  438.     done += actual;
  439.     if (actual != todo)    /* eof reached */
  440.         return done;
  441.     remaining -= actual;
  442.     }
  443.     return done;
  444. }
  445.  
  446. /* copy TOS relocation table from `from` to `to`. Copy bytes until NUL byte or
  447.    first 4 bytes if == 0l.
  448.    returns length of relocation table or -1 in case of an error */
  449.  
  450. long 
  451. copy_relo(name,from,to)
  452. char *name;
  453. int from,to;
  454. {
  455.   long res=0;
  456.   long bytes;
  457.   char *end;
  458.   int finished=0;
  459.  
  460.   res=lread( from, mybuf, sizeof(long) );
  461.   if( res!=0 && res!=sizeof(long) ) {
  462.     report( "Error reading\n" );
  463.     return -1;
  464.   }
  465.  
  466.   if( res==0 ) {
  467.     report("Warning: ");  /* I think empty relocation tables are allowed,
  468.     report(name);            but could cause trouble with certain programs */
  469.     report( ": No relocation table\n" );
  470.     return 0; 
  471.   }
  472.   if( lwrite(to,mybuf,res)!=res ) {
  473.     report(name);
  474.     report( ": Error writing\n" );
  475.     return -1;
  476.   }
  477.  
  478.   res=sizeof(long);
  479.   if( *(long*)mybuf == 0 ) return res; /* This is a clean version of an empty
  480.                         relocation table                   */
  481.   while(!finished) {
  482.     if( (bytes=lread(from,mybuf,NEWBUFSIZ))<0 ) {
  483.       report(name);
  484.       report( ": Error reading\n" );
  485.       return -1;
  486.     }
  487.     if( bytes==0 ) {
  488.       report( "Warning: " );
  489.       report(name);
  490.       report( ": Unterminated relocation table\n" );
  491.       return res;
  492.     }
  493. /* dont know if sozobon has memchr */
  494.     end=memchr(mybuf,0,bytes);
  495.     if(end) {
  496.       bytes=end-mybuf+1;
  497.       finished=1;
  498.     }
  499.     if( lwrite(to,mybuf,bytes)!=bytes ) {
  500.       report(name);
  501.       report(": Error writing\n");
  502.       return -1;
  503.     }
  504.   }
  505. }
  506.  
  507. void 
  508. report (s)
  509. char * s;
  510. {
  511.     lwrite (2, s, (long) strlen (s));
  512. }
  513.  
  514. /*
  515.  * Given a name of a file with reserved symbols create an array of
  516.  * reserved symbol names.  To terminate create an entry which starts
  517.  * with a null character.
  518.  */
  519.  
  520. #define LBUFSIZE 128
  521. #define NMSTEP 10
  522.  
  523. symstr_t       *
  524. mklist (fname)
  525. char * fname;
  526. {
  527.     FILE           *fp;
  528.     symstr_t       *list = (symstr_t *) NULL;
  529.     int             left = 0;
  530.     int             pos = 0;
  531.     int             i;
  532.     size_t          max_size = 1;
  533.     char            lbuf[LBUFSIZE];
  534.     char           *in, *out;
  535.  
  536. #ifdef atarist
  537.     if (NULL == (fp = fopen (fname, "rt"))) {
  538. #else
  539.     if (NULL == (fp = fopen (fname, "r"))) {
  540. #endif
  541.     report (fname);
  542.     report (" -- ");
  543.     usage ("cannot open this file\n");
  544.     }
  545.  
  546.     while (NULL != fgets (lbuf, LBUFSIZE, fp)) {
  547.     if (0 == left) {
  548.         max_size += NMSTEP;
  549.         if ((symstr_t *) NULL == list) {
  550.         list = (symstr_t *) malloc ( max_size * sizeof (symstr_t));
  551.         }
  552.         else {
  553.         list = (symstr_t *) realloc ((void *) list,
  554.                          max_size * sizeof (symstr_t));
  555.  
  556.         }
  557.         if ((symstr_t *) NULL == list) {
  558.         report ("out of memory making symbol list\n");
  559.         exit (-3);
  560.         }
  561.         left = NMSTEP;
  562.     }
  563.     /* strip all leading white space */
  564.     in = lbuf;
  565.     while (' ' == *in || '\t' == *in)
  566.         in++;
  567.     if ('\n' == *in)
  568.         continue;        /* empty line - skip it */
  569.     out = &list[pos][0];
  570.     for (i = GST_SYMLEN; i > 0; --i) {
  571.         if ('\n' == *in || ' ' == *in || '\t' == *in) {
  572.         while (i-- > 0) *out++ = '\0';
  573.         break;
  574.         }
  575.         *out++ = *in++;
  576.     }
  577.     pos++;
  578.     --left;
  579.     }                /* while */
  580.     if ((symstr_t *) NULL != list) {
  581.     list[pos][0] = '\0';    /* terminate created list */
  582.     }
  583.     return (list);
  584. }
  585.  
  586. /*
  587.  * From a file handle fd to a file handle tfd copy up to 'sbytes' bytes
  588.  * of a symbol table selecting only those symbols which have A_GLOBL
  589.  * flag set. Table nmlist is not really used, but is here for a uniform
  590.  * interface.  Returns a number of bytes copied.
  591.  */
  592. long
  593. sel_globs (fd, tfd, sbytes, nmlist)
  594. int fd, tfd;
  595. long sbytes;
  596. symstr_t * nmlist;
  597. {
  598.     long            lbytes = 0;
  599.     struct asym     cur_sym;
  600.     int            cont = 0;
  601.  
  602.     while (sbytes) {
  603.     if ((long)SIZEOF_ASYM != lread (fd, &cur_sym, 
  604.                         (long)SIZEOF_ASYM)) {
  605.         report ("error on reading symbol table\n");
  606.         break;
  607.     }
  608.     if (0 == cont) { /* if we are not dealing with the second part */
  609.         cont = (0 != (swap_short(cur_sym.a_type) & A_LNAM));
  610.         if (swap_short(cur_sym.a_type) & A_GLOBL) {
  611.         cont = -cont;
  612.         if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
  613.                             (long)SIZEOF_ASYM)) {
  614.             report ("error on writing symbol table\n");
  615.             break;
  616.         }
  617.         lbytes += SIZEOF_ASYM;
  618.         }
  619.     }
  620.     else { /* this was an extended symbol */
  621.         if (cont < 0) {  /* if global then write */
  622.         if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
  623.                             (long)SIZEOF_ASYM)) {
  624.             report ("error on writing symbol table\n");
  625.             break;
  626.         }
  627.         lbytes += SIZEOF_ASYM;
  628.         }
  629.         cont = 0;
  630.     }
  631.     sbytes -= SIZEOF_ASYM;
  632.     }
  633.     return (lbytes);
  634. }
  635.  
  636. /*
  637.  * From a file handle fd to a file handle tfd copy up to 'sbytes' bytes
  638.  * of a symbol table selecting only those symbols which are on nmlist.
  639.  * Free nmlist if different from a default global one.
  640.  * Returns a number of bytes copied.
  641.  */
  642. long
  643. sel_listed (fd, tfd, sbytes, nmlist)
  644. int fd, tfd;
  645. long sbytes;
  646. symstr_t * nmlist;
  647. {
  648.     long            lbytes = 0;
  649.     symstr_t       *kname;
  650.     struct asym     cur_sym, spare;
  651.  
  652.     if ((symstr_t *) NULL == nmlist)
  653.     return (0L);
  654.  
  655.     while (sbytes) {
  656.     if ((long)SIZEOF_ASYM != lread (fd, &cur_sym,
  657.                         (long) SIZEOF_ASYM)) {
  658.         report ("error on reading symbol table\n");
  659.         break;
  660.     }
  661.     for (kname = nmlist; '\0' != **kname; kname++) {
  662.         if (0 == strncmp (&(*kname)[0], &cur_sym.a_name[0], SYMLEN)) {
  663.         if ((A_LNAM & swap_short(cur_sym.a_type)) == A_LNAM) { /* if extended */
  664.             if ((long)SIZEOF_ASYM != lread (fd, &spare,
  665.                         (long)SIZEOF_ASYM)) {
  666.             report ("error on reading symbol table\n");
  667.             goto leave;  /* skip two loop levels */
  668.             }
  669.             sbytes -= SIZEOF_ASYM;
  670.             if (strncmp (&(*kname)[SYMLEN], (char *)&spare,
  671.                  GST_SYMLEN-SYMLEN))
  672.               continue;
  673.         }
  674.         if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
  675.                         (long)SIZEOF_ASYM)) {
  676.             report ("error on writing symbol table\n");
  677.             goto leave;
  678.         }
  679.         if ((swap_short(cur_sym.a_type) & A_LNAM) == A_LNAM)
  680.           {
  681.             if (lwrite (tfd, &spare, (long)SIZEOF_ASYM) != SIZEOF_ASYM)
  682.               {
  683.             report ("error on writing symbol table\n");
  684.             goto leave;
  685.               }
  686.             lbytes += SIZEOF_ASYM;
  687.           }
  688.         lbytes += SIZEOF_ASYM;
  689.         break;
  690.         }
  691.     }  /* for */
  692.     sbytes -= SIZEOF_ASYM;
  693.     }  /* while */
  694. leave:
  695.     if (nmlist != stklist) {
  696.     free (nmlist);
  697.     nmlist = (symstr_t *) NULL;
  698.     }
  699.     return (lbytes);
  700. }
  701.  
  702. #ifdef WORD_ALIGNED
  703. /*
  704.  * read header -- return !0 on err
  705.  */
  706. #define ck_read(fd, addr, siz) \
  707.   if((long)siz != lread(fd, addr, (long)siz)) return !0;
  708.  
  709. int read_head (fd, a)
  710. int fd;
  711. struct aexec *a;
  712. {
  713.     ck_read(fd, &a->a_magic,   sizeof(a->a_magic));
  714.     ck_read(fd, &a->a_text,    sizeof(a->a_text));
  715.     ck_read(fd, &a->a_data,    sizeof(a->a_data));
  716.     ck_read(fd, &a->a_bss,     sizeof(a->a_bss));
  717.     ck_read(fd, &a->a_syms,    sizeof(a->a_syms));
  718.     ck_read(fd, &a->a_AZero1,  sizeof(a->a_AZero1));
  719.     ck_read(fd, &a->a_AZero2,  sizeof(a->a_AZero2));
  720.     ck_read(fd, &a->a_isreloc, sizeof(a->a_isreloc));
  721.  
  722.     return 0;
  723. }
  724. #endif
  725.  
  726.  
  727. #ifdef CROSSHPUX
  728. char *xmalloc(n)
  729. unsigned n;
  730. {
  731.     extern char *malloc();
  732.     char *ret = malloc(n);
  733.     
  734.     if(!ret)
  735.     {
  736.         fprintf(stderr,"Out of memory!\n");
  737.         exit(1);
  738.     }
  739.     return ret;
  740. }
  741. #endif
  742.  
  743. #ifdef BYTE_SWAP
  744.  
  745. /* these routines work for big endian machines as well, but are not needed */
  746.  
  747. long swap_long(l)
  748. long l;
  749. {
  750.   long l1=l;
  751.   unsigned char *p=(unsigned char *)&l1;
  752.  
  753.   return (long)p[3]|((long)p[2]<<8)|((long)p[1]<<16)|((long)p[0]<<24);
  754. }
  755.  
  756. short swap_short(s)
  757. short s;
  758. {
  759.   short s1=s;
  760.   unsigned char *p=(unsigned char *)&s1;
  761.  
  762.   return (short)p[1]|((short)p[0]<<8);
  763. }
  764.  
  765. #endif
  766.