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