home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / oxcc1433.zip / SRC / OBJ4LB.C < prev    next >
C/C++ Source or Header  |  1995-10-24  |  22KB  |  1,017 lines

  1. /* obj4lb.c    -- fiddle with symbols in an a.out or coff format file 
  2. ** Copyright (C) 1995    Norman D. Culver    All rights reserved.
  3. **
  4. ** COMPILE: (using djcc v1.12)
  5. **        gcc -O2 -o obj4lb obj4lb.c
  6. **        coff2exe -s go32.exe obj4lb
  7. */
  8.  
  9. #include <dos.h>
  10. #include <limits.h>
  11. #include <sys/types.h>
  12. #include <stdlib.h>
  13. #include <stdarg.h>
  14. #include <memory.h>
  15. #include <string.h>
  16. #include <stdio.h>
  17. #include <binimg.h>
  18.  
  19. #define coff_sym_is_fortrancommon(p) \
  20.     ((p->e_sclass == C_EXT) && (p->e_scnum == 0) && (p->e_value != 0))
  21. #define coff_sym_is_undefined(p) \
  22.     ((p->e_scnum == 0) && (p->e_sclass == C_EXT))
  23. #define coff_sym_is_global(p) \
  24.     (p->e_sclass == C_EXT)
  25.  
  26. /* USEFUL DEFINITIONS */
  27. #ifndef __GNUC__
  28. typedef unsigned int u_int;
  29. typedef unsigned char u_char;
  30. typedef unsigned short u_short;
  31. typedef unsigned long u_long;
  32. #endif
  33. typedef union {
  34.   u_short val;
  35.   u_char b[2];
  36. } SVAL;
  37.  
  38. typedef union {
  39.   u_long a0;
  40.   void *a1;
  41.   struct {
  42.     SVAL offset;
  43.     SVAL seg_addr;
  44.   }a2;
  45. } ADDR;
  46.  
  47. typedef struct _exports {
  48.     struct _exports *fptr;
  49.     char *name;
  50.     int len;
  51. } EXPORTS;
  52.  
  53. typedef struct _renames {
  54.     struct _renames *fptr;
  55.     char *oldname;
  56.     int oldlen;
  57.     char *newname;
  58.     int newlen;
  59. } RENAMES;
  60.  
  61. typedef struct _movdat {
  62.     struct _movdat *fptr;
  63.     unsigned long offset;
  64. } MOVDAT, *PMOVDAT;
  65.  
  66. typedef struct relocation_info RELINFO;
  67.  
  68. #define round_up(size,amt) \
  69. ((size&(amt-1)) ? size+(amt-(size&(amt-1))) : size)
  70.  
  71. /* LOCAL VARIABLES */
  72. static char infile[128];
  73. static char outfile[128];
  74. static char lb4file[128];
  75. static struct exec header;
  76. static FILE *ifd, *lb4fd, *ofd;
  77. static EXPORTS exports;
  78. static RENAMES renames;
  79. static EXPORTS *lexports;
  80. static RENAMES *lrenames;
  81. static MOVDAT moves;
  82. static MOVDAT *lmoves;
  83. static int rename_diftot;
  84. static long lowoffset;
  85. static char *strtbl;
  86. static char *nstrtbl;
  87. static long strsize;
  88. static long nstrsize;
  89. static int nsyms;
  90.  
  91. /* INPUT DATA FROM THE .o FILE */
  92.  
  93. static NLIST *symtbl;
  94. static char *text;
  95. static RELINFO *text_relocs;
  96. static int n_text_relocs;
  97. static char *data;
  98. static RELINFO *data_relocs;
  99. static int n_data_relocs;
  100.  
  101. /* coff stuff */
  102. typedef struct oxhdr {
  103.     unsigned short info;
  104.     unsigned short machine;
  105.     unsigned start_addr;
  106.     unsigned text_vaddr;
  107.     unsigned text_size;
  108.     unsigned text_fileaddr;
  109.     unsigned data_vaddr;
  110.     unsigned data_size;
  111.     unsigned data_fileaddr;
  112.     unsigned bss_vaddr;
  113.     unsigned bss_size;
  114.     unsigned image_size;
  115.     unsigned text_reloc_fileaddr;
  116.     unsigned text_reloc_size;
  117.     unsigned text_reloc_cnt;
  118.     unsigned data_reloc_fileaddr;
  119.     unsigned data_reloc_size;
  120.     unsigned data_reloc_cnt;
  121.     unsigned symbols_fileaddr;
  122.     unsigned symbols_size;
  123.     unsigned symbols_cnt;
  124.     unsigned strings_fileaddr;
  125.     unsigned strings_size;
  126.     unsigned section_headers_size;
  127. } OXHDR, *POXHDR;
  128.  
  129. typedef struct {
  130.     void *addr;
  131.     long size;    
  132.     unsigned long fileptr;
  133.     long cnt;
  134. } BUFS, *PBUFS;
  135.  
  136. static OXHDR xhdr;
  137. static unsigned char scntype[128];
  138. static PSCNHDR t,d,b,q,s;
  139. static PBUFS sbf;
  140. static PBUFS rbf;
  141. static PBUFS lbf;
  142. static PCOFF_SYMBOL coff_symtbl;
  143. static short bss_section;
  144.  
  145. /* start of subroutines */
  146.  
  147. static void *
  148. xmalloc (long n)
  149. {
  150. void *p;
  151.  
  152.   p = calloc (1,(size_t)n);
  153.   if (n > 0 && p == 0)
  154.   {
  155.     puts ("obj4lb: virtual memory exhausted");
  156.     exit (1);
  157.   }
  158.   return p;
  159. }
  160. static int
  161. isglobal(char *str)
  162. {
  163. EXPORTS *l = &exports;
  164.  
  165.     while(l->fptr)
  166.     {
  167.         l = l->fptr;
  168.         if(!strcmp(str, l->name))
  169.             return 1;
  170.     }
  171.     return 0;
  172. }
  173. static RENAMES *
  174. isrenamed(char *str)
  175. {
  176. RENAMES *r = &renames;
  177.  
  178.     while(r->fptr)
  179.     {
  180.         r = r->fptr;
  181.         if(!strcmp(str, r->oldname))
  182.             return r;
  183.     }
  184.     return NULL;
  185. }
  186. static void
  187. aout_get_rid_of_fortrancommon(NLIST *sp, int symidx, int setglobal)
  188. {/* move fortrancommon symbols to the bss segment */
  189. u_long bssbase = N_BSSADDR(header);
  190. u_long bssoffset = round_up(header.a_bss, sizeof(int));
  191. u_long symbsize = sp->n_value;
  192. u_long bssaddr = bssbase + bssoffset;
  193. RELINFO *r;
  194. int i;
  195. void *ldata;
  196.  
  197.     sp->n_value = bssaddr;
  198.     if(setglobal)
  199.         sp->n_type = N_BSS|N_EXT;
  200.     else
  201.         sp->n_type = N_BSS;
  202.     header.a_bss = bssoffset + symbsize;
  203.  
  204.     /* adjust all relocs which refence this variable */
  205.     for(i = 0, r=text_relocs; i < n_text_relocs; ++i, ++r)
  206.     {
  207.         if(r->r_extern && r->r_symbolnum == symidx)
  208.         {
  209.             ldata = &text[r->r_address];
  210.             r->r_extern = 0;
  211.             r->r_symbolnum = N_BSS;
  212.             if(r->r_length == 2)
  213.                 *((long *)ldata) += bssaddr;
  214.             else
  215.             {
  216.                 puts("4lb: non 32bit reloc encountered");
  217.                 exit(1);
  218.             }
  219.         }
  220.     }
  221.     for(i = 0, r=data_relocs; i < n_data_relocs; ++i, ++r)
  222.     {
  223.         if(r->r_extern && r->r_symbolnum == symidx)
  224.         {
  225.             ldata = &data[r->r_address];
  226.             r->r_extern = 0;
  227.             r->r_symbolnum = N_BSS;
  228.             if(r->r_length == 2)
  229.                 *((long *)ldata) += bssaddr;
  230.             else
  231.             {
  232.                 puts("4lb: non 32bit reloc encountered");
  233.                 exit(1);
  234.             }
  235.         }
  236.     }
  237. }
  238. static void
  239. aout_adjust_symbol(long oldoffset, long newoffset, int setglobal)
  240. {
  241. NLIST *sp;
  242. int i;
  243.  
  244.     for(i = 0, sp = symtbl; i < nsyms; ++i, ++sp)
  245.     {
  246.         if(sp->n_un.n_strx == oldoffset)
  247.         {/* newoffset is set negative to avoid reuse */
  248.             sp->n_un.n_strx = newoffset | 0x80000000;
  249.             if(sym_is_fortrancommon(sp))
  250.                 aout_get_rid_of_fortrancommon(sp, i, setglobal);
  251.             else if(setglobal)
  252.                 sp->n_type |= N_EXT;
  253.             else if(!sym_is_undefined(sp))
  254.                 sp->n_type &= ~N_EXT;
  255.             return;
  256.         }
  257.     }
  258. }
  259. static void
  260. coff_get_rid_of_fortrancommon(COFF_SYMBOL *sp, int symidx, int setglobal)
  261. {/* move fortrancommon symbols to the bss segment */
  262. PCOFF_HDR p = (PCOFF_HDR)&header;
  263. u_long bssbase = b->s_vaddr;
  264. u_long bssoffset = round_up(b->s_size, sizeof(int));
  265. u_long symbsize = sp->e_value;
  266. u_long bssaddr = bssbase + bssoffset;
  267. int i, j;
  268.  
  269.     sp->e_value = bssaddr;
  270.     sp->e_scnum = bss_section;
  271.     if(setglobal)
  272.         sp->e_sclass = C_EXT;
  273.     else
  274.         sp->e_sclass = C_STAT;
  275.     b->s_size = round_up(bssoffset + symbsize, sizeof(int));
  276.  
  277.     /* adjust all relocs which reference this variable */
  278.     for(i = 0; i < p->f_nscns; ++i)
  279.     {
  280.     COFF_RELOC *r;
  281.  
  282.         if((r = rbf[i].addr))
  283.         {
  284.         int cnt = rbf[i].cnt;
  285.         char *scndata = sbf[i].addr;
  286.         unsigned long s_vaddr = s[i].s_vaddr;
  287.  
  288.             for(j = 0; j < cnt; ++j, ++r)
  289.             {
  290.                 if(r->r_symndx == symidx)
  291.                 {
  292.                 void *ldata = &scndata[r->u.r_vaddr - s_vaddr];
  293.                     if(r->r_type == 0x0006)
  294.                     {
  295.                         *((long *)ldata) += bssaddr - symbsize;
  296.                     }
  297.                     else if(r->r_type == 0x0007)
  298.                     {
  299.                         puts("4lb: type 7 reloc encountered");
  300.                         exit(1);
  301.                     }
  302.                     else if(r->r_type == 0x0014)
  303.                     {
  304.                         puts("4lb: pcrel comdef encountered");
  305.                         exit(1);
  306.                     }
  307.                     else
  308.                     {
  309.                         puts("4lb: non 32bit reloc encountered");
  310.                         exit(1);
  311.                     }
  312.                 }
  313.             }
  314.         }
  315.     }
  316. }
  317. static void
  318. coff_adjust_symbol(long oldoffset, long newoffset, int setglobal)
  319. {
  320. COFF_SYMBOL *sp;
  321. int i;
  322.  
  323.     for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
  324.     {
  325.         if(sp->e.e.e_offset == oldoffset)
  326.         {/* newoffset is set negative to avoid reuse */
  327.             sp->e.e.e_offset = newoffset | 0x80000000;
  328.             if(coff_sym_is_fortrancommon(sp))
  329.                 coff_get_rid_of_fortrancommon(sp, i, setglobal);
  330.             else if(setglobal)
  331.                 sp->e_sclass = C_EXT;
  332.             else if(!coff_sym_is_undefined(sp))
  333.             {
  334.                 if(coff_sym_is_global(sp))
  335.                     sp->e_sclass = C_STAT;
  336.             }
  337.         }
  338.         if(sp->e_numaux)
  339.         {/* ignore aux records */
  340.             i += sp->e_numaux;
  341.             sp += sp->e_numaux;
  342.         }
  343.     }
  344. }
  345. static void
  346. adjust_strings(int format_fudge)
  347. {/* HERE'S THE BEEF -- WRITE A NEW STRING TABLE AND ADJUST SYMTAB */
  348. long istroff = lowoffset;
  349. long ostroff = lowoffset;
  350. char *ip, *ep, *op;
  351. int i;
  352.  
  353.     nstrsize = strsize + rename_diftot;
  354.     nstrtbl = xmalloc(nstrsize+12);
  355.     ip = strtbl+lowoffset;
  356.     op = nstrtbl+lowoffset;
  357.     ep = ip + strsize;
  358.  
  359.     while(ip < ep)
  360.     {/* scan over each of the strings in the old string table */
  361.     int global;
  362.     int    istrlen = strlen(ip);
  363.     int olen;
  364.     RENAMES *r;
  365.         if(istrlen > 0)
  366.         {
  367.             if((r = isrenamed(ip)))
  368.             {/* change the string on output */
  369.                 strcpy(op, r->newname);
  370.                 op += r->newlen+1;
  371.                 olen = r->newlen+1;
  372.                 global = isglobal(r->newname);
  373.             }
  374.             else
  375.             {/* use the old string on output */
  376.                 strcpy(op, ip);
  377.                 op += istrlen+1;
  378.                 olen = istrlen+1;
  379.                 global = isglobal(ip);
  380.             }
  381.             if(coff_symtbl)
  382.                 coff_adjust_symbol(istroff, ostroff, global);
  383.             else
  384.                 aout_adjust_symbol(istroff, ostroff, global);
  385.             ostroff += olen;
  386.         }
  387.         ip += istrlen+1;
  388.         istroff += istrlen+1;
  389.     }
  390.     nstrsize = ostroff + format_fudge;
  391.     /* reset the negative values for offsets */
  392.     if(coff_symtbl)
  393.     {
  394.     COFF_SYMBOL *sp;
  395.         for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
  396.         {
  397.             if(sp->e.e.e_offset & 0x80000000)
  398.                 sp->e.e.e_offset &= 0x7fffffff;
  399.             if(sp->e_numaux)
  400.             {/* ignore aux records */
  401.                 i += sp->e_numaux;
  402.                 sp += sp->e_numaux;
  403.             }
  404.         }
  405.     }
  406.     else
  407.     {
  408.     NLIST *sp;
  409.         for(i = 0, sp = symtbl; i < nsyms; ++i, ++sp)
  410.         {
  411.           if(sp->n_un.n_strx & 0x80000000)
  412.               sp->n_un.n_strx &= 0x7fffffff;
  413.         }
  414.     }
  415. }
  416. static int
  417. aout_read_symbols ()
  418. {
  419. int i;
  420. NLIST *sp;
  421.  
  422.   nsyms = header.a_syms / sizeof (NLIST);
  423.   if (nsyms == 0)
  424.     return 1;
  425.  
  426.   symtbl = (NLIST *)xmalloc (header.a_syms);
  427.  
  428.   fseek (ifd, N_SYMOFF (header), 0);
  429.   fread ((char *)symtbl, sizeof(NLIST), nsyms, ifd);
  430.  
  431.   fseek (ifd, N_STROFF(header), 0);
  432.   fread ((char *)&strsize, sizeof strsize, 1, ifd);
  433.  
  434.   strtbl = xmalloc (strsize);
  435.   fseek (ifd, N_STROFF (header), 0);
  436.   fread ((char *)strtbl, (int)strsize, 1, ifd);
  437.  
  438.   lowoffset = 2000000;
  439.   for (i = 0, sp = symtbl; i < nsyms; i++, sp++)
  440.   {
  441.     if (sp->n_un.n_strx != 0)
  442.         if(sp->n_un.n_strx < lowoffset)
  443.             lowoffset = sp->n_un.n_strx;
  444.   }
  445. }
  446. static void
  447. aout_read_text_and_data()
  448. {
  449.   text = xmalloc(header.a_text);
  450.   data = xmalloc(header.a_data);
  451.  
  452.   if(header.a_text > 0)
  453.   {
  454.     fseek(ifd, N_TXTOFF(header), 0);
  455.     fread(text, (u_int)header.a_text, 1, ifd);
  456.   }
  457.   if(header.a_data > 0)
  458.   {
  459.     fseek(ifd, N_DATOFF(header), 0);
  460.     fread(data, (u_int)header.a_data, 1, ifd);
  461.   }
  462. }
  463. static int
  464. relcomp(const void *a,const void *b)
  465. {
  466.   return (int)((long)((RELINFO*)a)->r_address-(long)((RELINFO*)b)->r_address);
  467. }
  468. static void
  469. aout_read_relocs()
  470. {
  471. int i;
  472. RELINFO *reloc;
  473.  
  474.   n_text_relocs = header.a_trsize / sizeof (RELINFO); 
  475.   n_data_relocs = header.a_drsize / sizeof (RELINFO);
  476.  
  477.   if(n_text_relocs > 0)
  478.   {
  479.     text_relocs = xmalloc(header.a_trsize); 
  480.     fseek(ifd, N_TRELOFF(header), 0);
  481.     fread((char *)text_relocs, (u_int)header.a_trsize, 1, ifd);
  482.     qsort (text_relocs, n_text_relocs, sizeof (RELINFO), relcomp);
  483.   }
  484.  
  485.   if(n_data_relocs > 0)
  486.   {
  487.     data_relocs = xmalloc(header.a_drsize);    
  488.     fseek(ifd, N_DRELOFF(header), 0);
  489.     fread((char *)data_relocs, (u_int)header.a_drsize, 1, ifd);
  490.     qsort (data_relocs, n_data_relocs, sizeof (RELINFO),relcomp);
  491.   }
  492. }
  493.  
  494.  
  495. static int
  496. movcmp(char *s1, char *s2)
  497. {
  498. int i = E_SYMNMLEN;
  499.     while(i--)
  500.     {
  501.         if(*s1++ != *s2++)
  502.             return 1;
  503.     }
  504.     return 0;
  505. }
  506. static unsigned long
  507. mark_moved(PCOFF_SYMBOL sp)
  508. {
  509. MOVDAT *m = &moves;
  510.  
  511.     /* search current entries */
  512.     while(m->fptr)
  513.     {
  514.         m = m->fptr;
  515.         if(!movcmp(sp->e.e_name, strtbl+m->offset))
  516.             return m->offset;
  517.     }
  518.  
  519.     /* enter string in moved list */
  520.     if(!lmoves) lmoves = &moves;
  521.     lmoves->fptr = xmalloc(sizeof(MOVDAT));
  522.     lmoves = lmoves->fptr;        
  523.     lmoves->offset = strsize+4;
  524.  
  525.     memcpy(strtbl+lmoves->offset, sp->e.e_name, E_SYMNMLEN);
  526.     strsize += E_SYMNMLEN+1;
  527.     return lmoves->offset;
  528. }
  529. static void
  530. fix_silly_coff_symtbl()
  531. {
  532. COFF_SYMBOL *sp;
  533. int i;
  534. int xtracnt = 0;
  535.  
  536.     for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
  537.     {
  538.         if(sp->e.e.e_zeroes)
  539.         {/* this, 8 char or less symbol may be moved to strtbl */
  540.             xtracnt += E_SYMNMLEN+1;
  541.         }
  542.         if(sp->e_numaux)
  543.         {/* ignore aux records */
  544.             i += sp->e_numaux;
  545.             sp += sp->e_numaux;
  546.         }
  547.     }
  548.     if(xtracnt > 0)
  549.     {
  550.     char *nt;
  551.         nt = calloc(1, strsize + xtracnt + 4);
  552.         memcpy(nt, strtbl, strsize + 4);
  553.         free(strtbl);
  554.         strtbl = nt;
  555.  
  556.         for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
  557.         {
  558.             if(sp->e.e.e_zeroes)
  559.             {/* this, 8 char or less symbol must be moved to strtbl */
  560.                 sp->e.e.e_offset = mark_moved(sp);
  561.                 sp->e.e.e_zeroes = 0;
  562.             }
  563.             if(sp->e_numaux)
  564.             {/* ignore aux records */
  565.                 i += sp->e_numaux;
  566.                 sp += sp->e_numaux;
  567.             }
  568.         }
  569.         *((unsigned long *)strtbl) = strsize;
  570.     }
  571. }
  572. static void
  573. coff_read_stuff()
  574. {
  575. PCOFF_HDR p = (PCOFF_HDR)&header;
  576. POXHDR hdr = &xhdr;
  577. int i;
  578.     if(p->f_opthdr)
  579.     {/* optional header is present, wrong file type */
  580.         puts("4lb: coff optional header encountered, wrong file type");
  581.         exit(1);
  582.     }
  583.     /* load section headers */
  584.     hdr->section_headers_size = p->f_nscns * sizeof(SCNHDR);
  585.     s = malloc(hdr->section_headers_size);
  586.     fseek(ifd, sizeof(COFF_HDR), 0);
  587.     fread(s, 1, hdr->section_headers_size, ifd);
  588.  
  589.     /* scan section headers */
  590.     t = d = b = 0;
  591.     for(i = 0; i < p->f_nscns; ++i)
  592.     {/* find the text, data, and bss sections */
  593.         q = &s[i];
  594.         if(!strcmp(q->s_name, ".text"))
  595.         {
  596.              t = q;
  597.             scntype[i+1] = N_TEXT;
  598.         }
  599.         else if(!strcmp(q->s_name, ".data"))
  600.         {
  601.             d = q;
  602.             scntype[i+1] = N_DATA;
  603.         }
  604.         else if(!strcmp(q->s_name, ".bss"))
  605.         {
  606.             b = q;
  607.             scntype[i+1] = N_BSS;
  608.             bss_section = i+1;
  609.         }
  610.     }
  611.     if(!t || !d || !b)
  612.     {
  613.         puts("4lb: missing text data or bss section");
  614.         exit(1);
  615.     }
  616.     hdr->start_addr = 0;
  617.     hdr->text_size = t->s_size;
  618.     hdr->data_size = d->s_size;
  619.     hdr->bss_size = b->s_size;
  620.     hdr->text_fileaddr = t->s_scnptr;
  621.     hdr->data_fileaddr = d->s_scnptr;
  622.     hdr->text_vaddr = t->s_vaddr;
  623.     hdr->data_vaddr = d->s_vaddr;
  624.     hdr->bss_vaddr = b->s_vaddr;
  625.     hdr->image_size = hdr->text_size + hdr->data_size + hdr->bss_size;
  626.     hdr->text_reloc_fileaddr = t->s_relptr;
  627.     hdr->text_reloc_size = t->s_nreloc * COFF_RELOC_SIZE;
  628.     hdr->text_reloc_cnt  = t->s_nreloc;
  629.     hdr->data_reloc_fileaddr = d->s_relptr;
  630.     hdr->data_reloc_size = d->s_nreloc * COFF_RELOC_SIZE;
  631.     hdr->data_reloc_cnt  = d->s_nreloc;
  632.     if(        (hdr->symbols_fileaddr = p->f_symptr)
  633.         &&    (hdr->symbols_cnt = p->f_nsyms)
  634.       )/* you just can't tell what some utilities will do */
  635.     {
  636.     long temp;
  637.  
  638.         hdr->symbols_size = p->f_nsyms * COFF_SYMBOL_SIZE;
  639.         hdr->strings_fileaddr = hdr->symbols_fileaddr + hdr->symbols_size;
  640.  
  641.         fseek(ifd, hdr->strings_fileaddr, 0);
  642.         if(fread(&temp, 1, 4, ifd) != 4)
  643.         {
  644.             puts("4lb: no strings in coff file");
  645.             exit(1);
  646.         }
  647.         hdr->strings_size = strsize = nstrsize = temp;
  648.         nsyms = hdr->symbols_cnt;
  649.     }
  650.     else
  651.     {
  652.         puts("4lb: no symbols in coff file");
  653.         exit(1);
  654.     }
  655.     sbf = calloc(1, p->f_nscns * sizeof(BUFS));
  656.     rbf = calloc(1, p->f_nscns * sizeof(BUFS));
  657.     lbf = calloc(1, p->f_nscns * sizeof(BUFS));
  658.  
  659.     for(i = 0; i < p->f_nscns; ++i)
  660.     {/* load each of the sections, plus relocs and linenos */
  661.         q = &s[i];
  662.         if(q->s_scnptr)
  663.         {
  664.             sbf[i].size = q->s_size;
  665.              sbf[i].addr = malloc(sbf[i].size);
  666.             sbf[i].fileptr = q->s_scnptr;
  667.             fseek(ifd, sbf[i].fileptr, 0);
  668.             fread(sbf[i].addr, 1, sbf[i].size, ifd);
  669.             if(q->s_nreloc > 0)
  670.             {
  671.                 rbf[i].size = q->s_nreloc*COFF_RELOC_SIZE;
  672.                 rbf[i].addr = malloc(rbf[i].size);;
  673.                 rbf[i].fileptr = q->s_relptr;
  674.                 rbf[i].cnt = q->s_nreloc;
  675.                 fseek(ifd, rbf[i].fileptr, 0);
  676.                 fread(rbf[i].addr, 1, rbf[i].size, ifd);
  677.             }
  678.             if(q->s_nlnno > 0)
  679.             {
  680.                 lbf[i].size = q->s_nlnno*COFF_LINENO_SIZE;
  681.                 lbf[i].addr = malloc(lbf[i].size);
  682.                 lbf[i].fileptr = q->s_lnnoptr;
  683.                 lbf[i].cnt = q->s_nlnno;
  684.                 fseek(ifd, lbf[i].fileptr, 0);
  685.                 fread(lbf[i].addr, 1, lbf[i].size, ifd);
  686.             }
  687.         }
  688.     }
  689.     /* load the symbols and strings */
  690.     coff_symtbl = malloc(hdr->symbols_size);
  691.     fseek(ifd, hdr->symbols_fileaddr, 0);
  692.     fread(coff_symtbl, 1, hdr->symbols_size, ifd);
  693.     nstrtbl = strtbl = malloc(hdr->strings_size+4);
  694.     fseek(ifd, hdr->strings_fileaddr, 0);
  695.     fread(strtbl, 1, hdr->strings_size+4, ifd);
  696.     lowoffset = 4;
  697.     fix_silly_coff_symtbl();
  698. }
  699.  
  700. static void
  701. usage()
  702. {
  703.   puts("Usage: obj4lb infile");
  704.   puts("  infile must be in a.out or coff format.");
  705.   puts("  outfile will be the suffix .olb");
  706.   puts("  the specification file should have the suffix .4lb");
  707.   exit(0);
  708. }
  709. static void
  710. lose_backslashes(char *p)
  711. {
  712.   while(*p)
  713.   {
  714.     if(*p == '\\')
  715.       *p = '/';
  716.     ++p;
  717.   }
  718. }
  719. static int
  720. proc_infile(char *name)
  721. {
  722.   ifd = fopen(name, "r+b");
  723.   if(!ifd) {
  724.       printf("4lb: Cannot open input file %s\n", infile);
  725.     exit(1);
  726.   }
  727.   if(fread((char *)&header, sizeof(struct exec), 1, ifd) != 1)
  728.   {
  729.     printf("4lb: cannot read %s\n", name);
  730.     exit(1);
  731.   }
  732.   if(N_MAGIC(header) == OMAGIC)
  733.   {
  734.     aout_read_symbols();
  735.     aout_read_text_and_data();
  736.     aout_read_relocs();
  737.   }
  738.   else if(N_MAGIC(header) == IMAGIC)
  739.   {
  740.     coff_read_stuff();
  741.   }
  742.   else
  743.   {
  744.     printf("4lb: incorrect filetype: %s magic=%x\n", name, N_MAGIC(header));
  745.     exit(1);
  746.   }
  747.   return 1;
  748. }
  749. static void
  750. fix_suffix(char *str, char *suf)
  751. {
  752. char *cp;
  753.     if((cp = strrchr(str, '.')) != NULL)
  754.          strcpy(cp, suf);
  755.     else strcat(str, suf);
  756. }
  757. static char *
  758. find_sym(char *cp)
  759. {
  760.     while(*cp && (*cp == ':' || isspace(*cp)))
  761.         ++cp;
  762.  
  763.     if(*cp) {
  764.     char *np=cp;    
  765.         
  766.         while(*np && *np != ':' && !isspace(*np))
  767.             ++np;
  768.         if(*np)
  769.             *np = '\0';
  770.         return cp;
  771.     }
  772.     return NULL;
  773. }
  774. static int
  775. sym_exists(const char *cp, int len)
  776. {
  777. RENAMES *r = &renames;
  778. char *sp = strtbl;
  779. char *ep = strtbl + strsize;
  780.  
  781.     while(r->fptr)
  782.     {
  783.         r = r->fptr;
  784.         if(!strcmp(cp, r->newname))
  785.         {
  786.             cp = r->oldname;
  787.             len = r->oldlen;
  788.             break;            
  789.         }
  790.     }
  791.     while(sp < ep)
  792.     {
  793.     int splen = strlen(sp);
  794.         if(splen == len)
  795.           if(!strcmp(sp,cp))
  796.             return 1;
  797.         sp += splen+1;
  798.     }
  799.     return 0;
  800. }
  801. static void
  802. proc_4lb()
  803. {/* Process the specification file */
  804. char buf[200];
  805. char *cp;
  806.  
  807.     lexports = &exports;
  808.     lrenames = &renames;
  809.     while(fgets(buf, 190, lb4fd))
  810.     {
  811.         if((cp = strchr(buf, ':')) == NULL)
  812.             continue;
  813.         if(!strncmp(buf, "export", 6))
  814.         {
  815.             if((cp = find_sym(cp)) != NULL)
  816.             {
  817.             int len;
  818.             char *strloc;
  819.                 len = strlen(cp);
  820.                 if(sym_exists(cp, len))
  821.                 {
  822.                     strloc = xmalloc(len+1);
  823.                     strcpy(strloc, cp);
  824.                     lexports->fptr = xmalloc(sizeof(EXPORTS));
  825.                     lexports = lexports->fptr;
  826.                     lexports->name = strloc;
  827.                     lexports->len = len;
  828.                 }
  829.             }
  830.         }
  831.         else if(!strncmp(buf, "rename", 6))
  832.         {
  833.             if((cp = find_sym(cp)) != NULL)
  834.             {
  835.             int oldlen;
  836.             char *oldstr;
  837.  
  838.                 oldlen = strlen(cp);
  839.                 if(sym_exists(cp, oldlen))
  840.                 {
  841.                   oldstr = cp;
  842.                   cp += oldlen+1;
  843.                   if((cp = find_sym(cp)) != NULL)
  844.                   {
  845.                   int newlen = strlen(cp);
  846.                   char *newstr = cp;
  847.                   char *oldloc = xmalloc(oldlen+1);
  848.                   char *newloc = xmalloc(newlen+1);
  849.                     strcpy(oldloc, oldstr);
  850.                     strcpy(newloc, newstr);
  851.                     lrenames->fptr = xmalloc(sizeof(RENAMES));
  852.                     lrenames = lrenames->fptr;
  853.                     lrenames->oldname = oldloc;
  854.                     lrenames->oldlen = oldlen;
  855.                     lrenames->newname = newloc;
  856.                     lrenames->newlen = newlen; 
  857.                     rename_diftot += newlen - oldlen;
  858.                   }
  859.                 }
  860.             }
  861.         }
  862.     }
  863. }
  864. static void
  865. coff_proc_outfile(FILE *fd)
  866. {/* write coff format output file */
  867. PCOFF_HDR p = (PCOFF_HDR)&header;
  868. POXHDR hdr = &xhdr;
  869. int i;
  870.  
  871.     /* rename symbols and set exported symbols to global */
  872.     adjust_strings(0);
  873.  
  874.     fseek(fd, 0, 0);
  875.  
  876.     /* header */
  877.     fwrite(p, sizeof(COFF_HDR), 1, fd);
  878.  
  879.     /* section headers */
  880.     fwrite(s, hdr->section_headers_size, 1, fd);
  881.  
  882.     /* sections */
  883.     for(i = 0; i < p->f_nscns; ++i)
  884.     {
  885.     PSCNHDR q = &s[i];
  886.         if(q->s_scnptr)
  887.         {/* section has writeable data */
  888.             q->s_scnptr = ftell(fd);    /* new file offset */
  889.             fwrite(sbf[i].addr, sbf[i].size, 1, fd);
  890.         }
  891.     }
  892.     /* relocs */
  893.     for(i = 0; i < p->f_nscns; ++i)
  894.     {
  895.     PSCNHDR q = &s[i];
  896.         if(q->s_nreloc > 0 && rbf[i].size > 0)
  897.         {/* section has relocs */
  898.             q->s_relptr = ftell(fd);
  899.             fwrite(rbf[i].addr, rbf[i].size, 1, fd);
  900.         }
  901.         else
  902.         {
  903.             q->s_nreloc = 0;
  904.             q->s_relptr = 0;
  905.         }
  906.     }
  907.     /* line numbers */
  908.     for(i = 0; i < p->f_nscns; ++i)
  909.     {
  910.     PSCNHDR q = &s[i];
  911.         if(q->s_nlnno > 0 && lbf[i].size > 0)
  912.         {/* section has line numbers */
  913.             q->s_lnnoptr = ftell(fd);
  914.             fwrite(lbf[i].addr, lbf[i].size, 1, fd);
  915.         }
  916.         else
  917.         {
  918.             q->s_nlnno = 0;
  919.             q->s_lnnoptr = 0;
  920.         }
  921.     }
  922.     /* symbols */
  923.     p->f_symptr = ftell(fd);
  924.     fwrite(coff_symtbl, hdr->symbols_size, 1, fd);    
  925.  
  926.     /* strings */
  927.     fwrite((char *)&nstrsize, sizeof(nstrsize), 1, fd);
  928.     if(nstrsize)
  929.       fwrite(nstrtbl+sizeof(nstrsize),nstrsize,1,fd);
  930.  
  931.     /* reset section headers and symbols */
  932.     fflush(fd);
  933.     fseek(fd, 0, 0);
  934.     fwrite(p, sizeof(COFF_HDR), 1, fd);
  935.     fwrite(s, hdr->section_headers_size, 1, fd);
  936.     fflush(fd);
  937. }
  938. static void
  939. aout_proc_outfile(FILE *fd)
  940. {/* write aout format output file */
  941.  
  942.     /* rename symbols and set exported symbols to global */
  943.     adjust_strings(sizeof(nstrsize));
  944.  
  945.     fseek(fd, 0, 0);
  946.  
  947.     /* header */
  948.     fwrite((char *)&header, sizeof(struct exec), 1, fd);
  949.  
  950.     /* text */
  951.     if(header.a_text)
  952.         fwrite(text, (u_int)header.a_text, 1, fd);
  953.  
  954.     /* data */
  955.     if(header.a_data)
  956.         fwrite(data, (u_int)header.a_data, 1, fd);
  957.  
  958.     /* text relocs */
  959.     if(header.a_trsize)
  960.         fwrite((char *)text_relocs, (u_int)header.a_trsize, 1, fd);
  961.  
  962.     /* data relocs */
  963.     if(header.a_drsize);
  964.         fwrite((char *)data_relocs, (u_int)header.a_drsize, 1, fd);
  965.  
  966.     /* symbol table */
  967.     if(header.a_syms)
  968.         fwrite((char *)symtbl, (u_int)header.a_syms, 1, fd);
  969.  
  970.     /* strings */
  971.     fwrite((char *)&nstrsize, sizeof(nstrsize), 1, fd);
  972.     if(nstrsize)
  973.       fwrite(nstrtbl+sizeof(nstrsize),nstrsize-sizeof(nstrsize),1,fd);
  974.     fflush(fd);
  975. }
  976. #ifdef SKELETON
  977. int obj4lb(int argc, char **argv)
  978. #else
  979. int main(int argc, char **argv)
  980. #endif
  981. {
  982. char *str;
  983. int i, j;
  984. char chr;
  985.  
  986.  
  987.   if (argc != 2) usage();
  988.   strcpy(infile,argv[1]);
  989.   lose_backslashes(infile);
  990.   strcpy(outfile,infile);
  991.   strcpy(lb4file,infile);
  992.   fix_suffix(outfile, ".olb");
  993.   fix_suffix(lb4file, ".4lb");
  994.  
  995.   /* process the input file */
  996.   if(proc_infile(infile))
  997.   {
  998.       fclose(ifd);
  999.       /* process the specification file */
  1000.       lb4fd = fopen(lb4file, "r"); 
  1001.       if(lb4fd)
  1002.       {
  1003.         proc_4lb();
  1004.         fclose(lb4fd);
  1005.       } else {
  1006.           puts("4lb: warning export file not found");
  1007.       }
  1008.       ofd = fopen(outfile, "w+b");
  1009.       if(N_MAGIC(header) == OMAGIC)
  1010.         aout_proc_outfile(ofd);
  1011.       else
  1012.           coff_proc_outfile(ofd);
  1013.       fclose(ofd);
  1014.   }
  1015.   return 0;   
  1016. }
  1017.