home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
oxcc1433.zip
/
SRC
/
OBJ4LB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-24
|
22KB
|
1,017 lines
/* obj4lb.c -- fiddle with symbols in an a.out or coff format file
** Copyright (C) 1995 Norman D. Culver All rights reserved.
**
** COMPILE: (using djcc v1.12)
** gcc -O2 -o obj4lb obj4lb.c
** coff2exe -s go32.exe obj4lb
*/
#include <dos.h>
#include <limits.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdarg.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>
#include <binimg.h>
#define coff_sym_is_fortrancommon(p) \
((p->e_sclass == C_EXT) && (p->e_scnum == 0) && (p->e_value != 0))
#define coff_sym_is_undefined(p) \
((p->e_scnum == 0) && (p->e_sclass == C_EXT))
#define coff_sym_is_global(p) \
(p->e_sclass == C_EXT)
/* USEFUL DEFINITIONS */
#ifndef __GNUC__
typedef unsigned int u_int;
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long u_long;
#endif
typedef union {
u_short val;
u_char b[2];
} SVAL;
typedef union {
u_long a0;
void *a1;
struct {
SVAL offset;
SVAL seg_addr;
}a2;
} ADDR;
typedef struct _exports {
struct _exports *fptr;
char *name;
int len;
} EXPORTS;
typedef struct _renames {
struct _renames *fptr;
char *oldname;
int oldlen;
char *newname;
int newlen;
} RENAMES;
typedef struct _movdat {
struct _movdat *fptr;
unsigned long offset;
} MOVDAT, *PMOVDAT;
typedef struct relocation_info RELINFO;
#define round_up(size,amt) \
((size&(amt-1)) ? size+(amt-(size&(amt-1))) : size)
/* LOCAL VARIABLES */
static char infile[128];
static char outfile[128];
static char lb4file[128];
static struct exec header;
static FILE *ifd, *lb4fd, *ofd;
static EXPORTS exports;
static RENAMES renames;
static EXPORTS *lexports;
static RENAMES *lrenames;
static MOVDAT moves;
static MOVDAT *lmoves;
static int rename_diftot;
static long lowoffset;
static char *strtbl;
static char *nstrtbl;
static long strsize;
static long nstrsize;
static int nsyms;
/* INPUT DATA FROM THE .o FILE */
static NLIST *symtbl;
static char *text;
static RELINFO *text_relocs;
static int n_text_relocs;
static char *data;
static RELINFO *data_relocs;
static int n_data_relocs;
/* coff stuff */
typedef struct oxhdr {
unsigned short info;
unsigned short machine;
unsigned start_addr;
unsigned text_vaddr;
unsigned text_size;
unsigned text_fileaddr;
unsigned data_vaddr;
unsigned data_size;
unsigned data_fileaddr;
unsigned bss_vaddr;
unsigned bss_size;
unsigned image_size;
unsigned text_reloc_fileaddr;
unsigned text_reloc_size;
unsigned text_reloc_cnt;
unsigned data_reloc_fileaddr;
unsigned data_reloc_size;
unsigned data_reloc_cnt;
unsigned symbols_fileaddr;
unsigned symbols_size;
unsigned symbols_cnt;
unsigned strings_fileaddr;
unsigned strings_size;
unsigned section_headers_size;
} OXHDR, *POXHDR;
typedef struct {
void *addr;
long size;
unsigned long fileptr;
long cnt;
} BUFS, *PBUFS;
static OXHDR xhdr;
static unsigned char scntype[128];
static PSCNHDR t,d,b,q,s;
static PBUFS sbf;
static PBUFS rbf;
static PBUFS lbf;
static PCOFF_SYMBOL coff_symtbl;
static short bss_section;
/* start of subroutines */
static void *
xmalloc (long n)
{
void *p;
p = calloc (1,(size_t)n);
if (n > 0 && p == 0)
{
puts ("obj4lb: virtual memory exhausted");
exit (1);
}
return p;
}
static int
isglobal(char *str)
{
EXPORTS *l = &exports;
while(l->fptr)
{
l = l->fptr;
if(!strcmp(str, l->name))
return 1;
}
return 0;
}
static RENAMES *
isrenamed(char *str)
{
RENAMES *r = &renames;
while(r->fptr)
{
r = r->fptr;
if(!strcmp(str, r->oldname))
return r;
}
return NULL;
}
static void
aout_get_rid_of_fortrancommon(NLIST *sp, int symidx, int setglobal)
{/* move fortrancommon symbols to the bss segment */
u_long bssbase = N_BSSADDR(header);
u_long bssoffset = round_up(header.a_bss, sizeof(int));
u_long symbsize = sp->n_value;
u_long bssaddr = bssbase + bssoffset;
RELINFO *r;
int i;
void *ldata;
sp->n_value = bssaddr;
if(setglobal)
sp->n_type = N_BSS|N_EXT;
else
sp->n_type = N_BSS;
header.a_bss = bssoffset + symbsize;
/* adjust all relocs which refence this variable */
for(i = 0, r=text_relocs; i < n_text_relocs; ++i, ++r)
{
if(r->r_extern && r->r_symbolnum == symidx)
{
ldata = &text[r->r_address];
r->r_extern = 0;
r->r_symbolnum = N_BSS;
if(r->r_length == 2)
*((long *)ldata) += bssaddr;
else
{
puts("4lb: non 32bit reloc encountered");
exit(1);
}
}
}
for(i = 0, r=data_relocs; i < n_data_relocs; ++i, ++r)
{
if(r->r_extern && r->r_symbolnum == symidx)
{
ldata = &data[r->r_address];
r->r_extern = 0;
r->r_symbolnum = N_BSS;
if(r->r_length == 2)
*((long *)ldata) += bssaddr;
else
{
puts("4lb: non 32bit reloc encountered");
exit(1);
}
}
}
}
static void
aout_adjust_symbol(long oldoffset, long newoffset, int setglobal)
{
NLIST *sp;
int i;
for(i = 0, sp = symtbl; i < nsyms; ++i, ++sp)
{
if(sp->n_un.n_strx == oldoffset)
{/* newoffset is set negative to avoid reuse */
sp->n_un.n_strx = newoffset | 0x80000000;
if(sym_is_fortrancommon(sp))
aout_get_rid_of_fortrancommon(sp, i, setglobal);
else if(setglobal)
sp->n_type |= N_EXT;
else if(!sym_is_undefined(sp))
sp->n_type &= ~N_EXT;
return;
}
}
}
static void
coff_get_rid_of_fortrancommon(COFF_SYMBOL *sp, int symidx, int setglobal)
{/* move fortrancommon symbols to the bss segment */
PCOFF_HDR p = (PCOFF_HDR)&header;
u_long bssbase = b->s_vaddr;
u_long bssoffset = round_up(b->s_size, sizeof(int));
u_long symbsize = sp->e_value;
u_long bssaddr = bssbase + bssoffset;
int i, j;
sp->e_value = bssaddr;
sp->e_scnum = bss_section;
if(setglobal)
sp->e_sclass = C_EXT;
else
sp->e_sclass = C_STAT;
b->s_size = round_up(bssoffset + symbsize, sizeof(int));
/* adjust all relocs which reference this variable */
for(i = 0; i < p->f_nscns; ++i)
{
COFF_RELOC *r;
if((r = rbf[i].addr))
{
int cnt = rbf[i].cnt;
char *scndata = sbf[i].addr;
unsigned long s_vaddr = s[i].s_vaddr;
for(j = 0; j < cnt; ++j, ++r)
{
if(r->r_symndx == symidx)
{
void *ldata = &scndata[r->u.r_vaddr - s_vaddr];
if(r->r_type == 0x0006)
{
*((long *)ldata) += bssaddr - symbsize;
}
else if(r->r_type == 0x0007)
{
puts("4lb: type 7 reloc encountered");
exit(1);
}
else if(r->r_type == 0x0014)
{
puts("4lb: pcrel comdef encountered");
exit(1);
}
else
{
puts("4lb: non 32bit reloc encountered");
exit(1);
}
}
}
}
}
}
static void
coff_adjust_symbol(long oldoffset, long newoffset, int setglobal)
{
COFF_SYMBOL *sp;
int i;
for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
{
if(sp->e.e.e_offset == oldoffset)
{/* newoffset is set negative to avoid reuse */
sp->e.e.e_offset = newoffset | 0x80000000;
if(coff_sym_is_fortrancommon(sp))
coff_get_rid_of_fortrancommon(sp, i, setglobal);
else if(setglobal)
sp->e_sclass = C_EXT;
else if(!coff_sym_is_undefined(sp))
{
if(coff_sym_is_global(sp))
sp->e_sclass = C_STAT;
}
}
if(sp->e_numaux)
{/* ignore aux records */
i += sp->e_numaux;
sp += sp->e_numaux;
}
}
}
static void
adjust_strings(int format_fudge)
{/* HERE'S THE BEEF -- WRITE A NEW STRING TABLE AND ADJUST SYMTAB */
long istroff = lowoffset;
long ostroff = lowoffset;
char *ip, *ep, *op;
int i;
nstrsize = strsize + rename_diftot;
nstrtbl = xmalloc(nstrsize+12);
ip = strtbl+lowoffset;
op = nstrtbl+lowoffset;
ep = ip + strsize;
while(ip < ep)
{/* scan over each of the strings in the old string table */
int global;
int istrlen = strlen(ip);
int olen;
RENAMES *r;
if(istrlen > 0)
{
if((r = isrenamed(ip)))
{/* change the string on output */
strcpy(op, r->newname);
op += r->newlen+1;
olen = r->newlen+1;
global = isglobal(r->newname);
}
else
{/* use the old string on output */
strcpy(op, ip);
op += istrlen+1;
olen = istrlen+1;
global = isglobal(ip);
}
if(coff_symtbl)
coff_adjust_symbol(istroff, ostroff, global);
else
aout_adjust_symbol(istroff, ostroff, global);
ostroff += olen;
}
ip += istrlen+1;
istroff += istrlen+1;
}
nstrsize = ostroff + format_fudge;
/* reset the negative values for offsets */
if(coff_symtbl)
{
COFF_SYMBOL *sp;
for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
{
if(sp->e.e.e_offset & 0x80000000)
sp->e.e.e_offset &= 0x7fffffff;
if(sp->e_numaux)
{/* ignore aux records */
i += sp->e_numaux;
sp += sp->e_numaux;
}
}
}
else
{
NLIST *sp;
for(i = 0, sp = symtbl; i < nsyms; ++i, ++sp)
{
if(sp->n_un.n_strx & 0x80000000)
sp->n_un.n_strx &= 0x7fffffff;
}
}
}
static int
aout_read_symbols ()
{
int i;
NLIST *sp;
nsyms = header.a_syms / sizeof (NLIST);
if (nsyms == 0)
return 1;
symtbl = (NLIST *)xmalloc (header.a_syms);
fseek (ifd, N_SYMOFF (header), 0);
fread ((char *)symtbl, sizeof(NLIST), nsyms, ifd);
fseek (ifd, N_STROFF(header), 0);
fread ((char *)&strsize, sizeof strsize, 1, ifd);
strtbl = xmalloc (strsize);
fseek (ifd, N_STROFF (header), 0);
fread ((char *)strtbl, (int)strsize, 1, ifd);
lowoffset = 2000000;
for (i = 0, sp = symtbl; i < nsyms; i++, sp++)
{
if (sp->n_un.n_strx != 0)
if(sp->n_un.n_strx < lowoffset)
lowoffset = sp->n_un.n_strx;
}
}
static void
aout_read_text_and_data()
{
text = xmalloc(header.a_text);
data = xmalloc(header.a_data);
if(header.a_text > 0)
{
fseek(ifd, N_TXTOFF(header), 0);
fread(text, (u_int)header.a_text, 1, ifd);
}
if(header.a_data > 0)
{
fseek(ifd, N_DATOFF(header), 0);
fread(data, (u_int)header.a_data, 1, ifd);
}
}
static int
relcomp(const void *a,const void *b)
{
return (int)((long)((RELINFO*)a)->r_address-(long)((RELINFO*)b)->r_address);
}
static void
aout_read_relocs()
{
int i;
RELINFO *reloc;
n_text_relocs = header.a_trsize / sizeof (RELINFO);
n_data_relocs = header.a_drsize / sizeof (RELINFO);
if(n_text_relocs > 0)
{
text_relocs = xmalloc(header.a_trsize);
fseek(ifd, N_TRELOFF(header), 0);
fread((char *)text_relocs, (u_int)header.a_trsize, 1, ifd);
qsort (text_relocs, n_text_relocs, sizeof (RELINFO), relcomp);
}
if(n_data_relocs > 0)
{
data_relocs = xmalloc(header.a_drsize);
fseek(ifd, N_DRELOFF(header), 0);
fread((char *)data_relocs, (u_int)header.a_drsize, 1, ifd);
qsort (data_relocs, n_data_relocs, sizeof (RELINFO),relcomp);
}
}
static int
movcmp(char *s1, char *s2)
{
int i = E_SYMNMLEN;
while(i--)
{
if(*s1++ != *s2++)
return 1;
}
return 0;
}
static unsigned long
mark_moved(PCOFF_SYMBOL sp)
{
MOVDAT *m = &moves;
/* search current entries */
while(m->fptr)
{
m = m->fptr;
if(!movcmp(sp->e.e_name, strtbl+m->offset))
return m->offset;
}
/* enter string in moved list */
if(!lmoves) lmoves = &moves;
lmoves->fptr = xmalloc(sizeof(MOVDAT));
lmoves = lmoves->fptr;
lmoves->offset = strsize+4;
memcpy(strtbl+lmoves->offset, sp->e.e_name, E_SYMNMLEN);
strsize += E_SYMNMLEN+1;
return lmoves->offset;
}
static void
fix_silly_coff_symtbl()
{
COFF_SYMBOL *sp;
int i;
int xtracnt = 0;
for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
{
if(sp->e.e.e_zeroes)
{/* this, 8 char or less symbol may be moved to strtbl */
xtracnt += E_SYMNMLEN+1;
}
if(sp->e_numaux)
{/* ignore aux records */
i += sp->e_numaux;
sp += sp->e_numaux;
}
}
if(xtracnt > 0)
{
char *nt;
nt = calloc(1, strsize + xtracnt + 4);
memcpy(nt, strtbl, strsize + 4);
free(strtbl);
strtbl = nt;
for(i = 0, sp = coff_symtbl; i < nsyms; ++i, ++sp)
{
if(sp->e.e.e_zeroes)
{/* this, 8 char or less symbol must be moved to strtbl */
sp->e.e.e_offset = mark_moved(sp);
sp->e.e.e_zeroes = 0;
}
if(sp->e_numaux)
{/* ignore aux records */
i += sp->e_numaux;
sp += sp->e_numaux;
}
}
*((unsigned long *)strtbl) = strsize;
}
}
static void
coff_read_stuff()
{
PCOFF_HDR p = (PCOFF_HDR)&header;
POXHDR hdr = &xhdr;
int i;
if(p->f_opthdr)
{/* optional header is present, wrong file type */
puts("4lb: coff optional header encountered, wrong file type");
exit(1);
}
/* load section headers */
hdr->section_headers_size = p->f_nscns * sizeof(SCNHDR);
s = malloc(hdr->section_headers_size);
fseek(ifd, sizeof(COFF_HDR), 0);
fread(s, 1, hdr->section_headers_size, ifd);
/* scan section headers */
t = d = b = 0;
for(i = 0; i < p->f_nscns; ++i)
{/* find the text, data, and bss sections */
q = &s[i];
if(!strcmp(q->s_name, ".text"))
{
t = q;
scntype[i+1] = N_TEXT;
}
else if(!strcmp(q->s_name, ".data"))
{
d = q;
scntype[i+1] = N_DATA;
}
else if(!strcmp(q->s_name, ".bss"))
{
b = q;
scntype[i+1] = N_BSS;
bss_section = i+1;
}
}
if(!t || !d || !b)
{
puts("4lb: missing text data or bss section");
exit(1);
}
hdr->start_addr = 0;
hdr->text_size = t->s_size;
hdr->data_size = d->s_size;
hdr->bss_size = b->s_size;
hdr->text_fileaddr = t->s_scnptr;
hdr->data_fileaddr = d->s_scnptr;
hdr->text_vaddr = t->s_vaddr;
hdr->data_vaddr = d->s_vaddr;
hdr->bss_vaddr = b->s_vaddr;
hdr->image_size = hdr->text_size + hdr->data_size + hdr->bss_size;
hdr->text_reloc_fileaddr = t->s_relptr;
hdr->text_reloc_size = t->s_nreloc * COFF_RELOC_SIZE;
hdr->text_reloc_cnt = t->s_nreloc;
hdr->data_reloc_fileaddr = d->s_relptr;
hdr->data_reloc_size = d->s_nreloc * COFF_RELOC_SIZE;
hdr->data_reloc_cnt = d->s_nreloc;
if( (hdr->symbols_fileaddr = p->f_symptr)
&& (hdr->symbols_cnt = p->f_nsyms)
)/* you just can't tell what some utilities will do */
{
long temp;
hdr->symbols_size = p->f_nsyms * COFF_SYMBOL_SIZE;
hdr->strings_fileaddr = hdr->symbols_fileaddr + hdr->symbols_size;
fseek(ifd, hdr->strings_fileaddr, 0);
if(fread(&temp, 1, 4, ifd) != 4)
{
puts("4lb: no strings in coff file");
exit(1);
}
hdr->strings_size = strsize = nstrsize = temp;
nsyms = hdr->symbols_cnt;
}
else
{
puts("4lb: no symbols in coff file");
exit(1);
}
sbf = calloc(1, p->f_nscns * sizeof(BUFS));
rbf = calloc(1, p->f_nscns * sizeof(BUFS));
lbf = calloc(1, p->f_nscns * sizeof(BUFS));
for(i = 0; i < p->f_nscns; ++i)
{/* load each of the sections, plus relocs and linenos */
q = &s[i];
if(q->s_scnptr)
{
sbf[i].size = q->s_size;
sbf[i].addr = malloc(sbf[i].size);
sbf[i].fileptr = q->s_scnptr;
fseek(ifd, sbf[i].fileptr, 0);
fread(sbf[i].addr, 1, sbf[i].size, ifd);
if(q->s_nreloc > 0)
{
rbf[i].size = q->s_nreloc*COFF_RELOC_SIZE;
rbf[i].addr = malloc(rbf[i].size);;
rbf[i].fileptr = q->s_relptr;
rbf[i].cnt = q->s_nreloc;
fseek(ifd, rbf[i].fileptr, 0);
fread(rbf[i].addr, 1, rbf[i].size, ifd);
}
if(q->s_nlnno > 0)
{
lbf[i].size = q->s_nlnno*COFF_LINENO_SIZE;
lbf[i].addr = malloc(lbf[i].size);
lbf[i].fileptr = q->s_lnnoptr;
lbf[i].cnt = q->s_nlnno;
fseek(ifd, lbf[i].fileptr, 0);
fread(lbf[i].addr, 1, lbf[i].size, ifd);
}
}
}
/* load the symbols and strings */
coff_symtbl = malloc(hdr->symbols_size);
fseek(ifd, hdr->symbols_fileaddr, 0);
fread(coff_symtbl, 1, hdr->symbols_size, ifd);
nstrtbl = strtbl = malloc(hdr->strings_size+4);
fseek(ifd, hdr->strings_fileaddr, 0);
fread(strtbl, 1, hdr->strings_size+4, ifd);
lowoffset = 4;
fix_silly_coff_symtbl();
}
static void
usage()
{
puts("Usage: obj4lb infile");
puts(" infile must be in a.out or coff format.");
puts(" outfile will be the suffix .olb");
puts(" the specification file should have the suffix .4lb");
exit(0);
}
static void
lose_backslashes(char *p)
{
while(*p)
{
if(*p == '\\')
*p = '/';
++p;
}
}
static int
proc_infile(char *name)
{
ifd = fopen(name, "r+b");
if(!ifd) {
printf("4lb: Cannot open input file %s\n", infile);
exit(1);
}
if(fread((char *)&header, sizeof(struct exec), 1, ifd) != 1)
{
printf("4lb: cannot read %s\n", name);
exit(1);
}
if(N_MAGIC(header) == OMAGIC)
{
aout_read_symbols();
aout_read_text_and_data();
aout_read_relocs();
}
else if(N_MAGIC(header) == IMAGIC)
{
coff_read_stuff();
}
else
{
printf("4lb: incorrect filetype: %s magic=%x\n", name, N_MAGIC(header));
exit(1);
}
return 1;
}
static void
fix_suffix(char *str, char *suf)
{
char *cp;
if((cp = strrchr(str, '.')) != NULL)
strcpy(cp, suf);
else strcat(str, suf);
}
static char *
find_sym(char *cp)
{
while(*cp && (*cp == ':' || isspace(*cp)))
++cp;
if(*cp) {
char *np=cp;
while(*np && *np != ':' && !isspace(*np))
++np;
if(*np)
*np = '\0';
return cp;
}
return NULL;
}
static int
sym_exists(const char *cp, int len)
{
RENAMES *r = &renames;
char *sp = strtbl;
char *ep = strtbl + strsize;
while(r->fptr)
{
r = r->fptr;
if(!strcmp(cp, r->newname))
{
cp = r->oldname;
len = r->oldlen;
break;
}
}
while(sp < ep)
{
int splen = strlen(sp);
if(splen == len)
if(!strcmp(sp,cp))
return 1;
sp += splen+1;
}
return 0;
}
static void
proc_4lb()
{/* Process the specification file */
char buf[200];
char *cp;
lexports = &exports;
lrenames = &renames;
while(fgets(buf, 190, lb4fd))
{
if((cp = strchr(buf, ':')) == NULL)
continue;
if(!strncmp(buf, "export", 6))
{
if((cp = find_sym(cp)) != NULL)
{
int len;
char *strloc;
len = strlen(cp);
if(sym_exists(cp, len))
{
strloc = xmalloc(len+1);
strcpy(strloc, cp);
lexports->fptr = xmalloc(sizeof(EXPORTS));
lexports = lexports->fptr;
lexports->name = strloc;
lexports->len = len;
}
}
}
else if(!strncmp(buf, "rename", 6))
{
if((cp = find_sym(cp)) != NULL)
{
int oldlen;
char *oldstr;
oldlen = strlen(cp);
if(sym_exists(cp, oldlen))
{
oldstr = cp;
cp += oldlen+1;
if((cp = find_sym(cp)) != NULL)
{
int newlen = strlen(cp);
char *newstr = cp;
char *oldloc = xmalloc(oldlen+1);
char *newloc = xmalloc(newlen+1);
strcpy(oldloc, oldstr);
strcpy(newloc, newstr);
lrenames->fptr = xmalloc(sizeof(RENAMES));
lrenames = lrenames->fptr;
lrenames->oldname = oldloc;
lrenames->oldlen = oldlen;
lrenames->newname = newloc;
lrenames->newlen = newlen;
rename_diftot += newlen - oldlen;
}
}
}
}
}
}
static void
coff_proc_outfile(FILE *fd)
{/* write coff format output file */
PCOFF_HDR p = (PCOFF_HDR)&header;
POXHDR hdr = &xhdr;
int i;
/* rename symbols and set exported symbols to global */
adjust_strings(0);
fseek(fd, 0, 0);
/* header */
fwrite(p, sizeof(COFF_HDR), 1, fd);
/* section headers */
fwrite(s, hdr->section_headers_size, 1, fd);
/* sections */
for(i = 0; i < p->f_nscns; ++i)
{
PSCNHDR q = &s[i];
if(q->s_scnptr)
{/* section has writeable data */
q->s_scnptr = ftell(fd); /* new file offset */
fwrite(sbf[i].addr, sbf[i].size, 1, fd);
}
}
/* relocs */
for(i = 0; i < p->f_nscns; ++i)
{
PSCNHDR q = &s[i];
if(q->s_nreloc > 0 && rbf[i].size > 0)
{/* section has relocs */
q->s_relptr = ftell(fd);
fwrite(rbf[i].addr, rbf[i].size, 1, fd);
}
else
{
q->s_nreloc = 0;
q->s_relptr = 0;
}
}
/* line numbers */
for(i = 0; i < p->f_nscns; ++i)
{
PSCNHDR q = &s[i];
if(q->s_nlnno > 0 && lbf[i].size > 0)
{/* section has line numbers */
q->s_lnnoptr = ftell(fd);
fwrite(lbf[i].addr, lbf[i].size, 1, fd);
}
else
{
q->s_nlnno = 0;
q->s_lnnoptr = 0;
}
}
/* symbols */
p->f_symptr = ftell(fd);
fwrite(coff_symtbl, hdr->symbols_size, 1, fd);
/* strings */
fwrite((char *)&nstrsize, sizeof(nstrsize), 1, fd);
if(nstrsize)
fwrite(nstrtbl+sizeof(nstrsize),nstrsize,1,fd);
/* reset section headers and symbols */
fflush(fd);
fseek(fd, 0, 0);
fwrite(p, sizeof(COFF_HDR), 1, fd);
fwrite(s, hdr->section_headers_size, 1, fd);
fflush(fd);
}
static void
aout_proc_outfile(FILE *fd)
{/* write aout format output file */
/* rename symbols and set exported symbols to global */
adjust_strings(sizeof(nstrsize));
fseek(fd, 0, 0);
/* header */
fwrite((char *)&header, sizeof(struct exec), 1, fd);
/* text */
if(header.a_text)
fwrite(text, (u_int)header.a_text, 1, fd);
/* data */
if(header.a_data)
fwrite(data, (u_int)header.a_data, 1, fd);
/* text relocs */
if(header.a_trsize)
fwrite((char *)text_relocs, (u_int)header.a_trsize, 1, fd);
/* data relocs */
if(header.a_drsize);
fwrite((char *)data_relocs, (u_int)header.a_drsize, 1, fd);
/* symbol table */
if(header.a_syms)
fwrite((char *)symtbl, (u_int)header.a_syms, 1, fd);
/* strings */
fwrite((char *)&nstrsize, sizeof(nstrsize), 1, fd);
if(nstrsize)
fwrite(nstrtbl+sizeof(nstrsize),nstrsize-sizeof(nstrsize),1,fd);
fflush(fd);
}
#ifdef SKELETON
int obj4lb(int argc, char **argv)
#else
int main(int argc, char **argv)
#endif
{
char *str;
int i, j;
char chr;
if (argc != 2) usage();
strcpy(infile,argv[1]);
lose_backslashes(infile);
strcpy(outfile,infile);
strcpy(lb4file,infile);
fix_suffix(outfile, ".olb");
fix_suffix(lb4file, ".4lb");
/* process the input file */
if(proc_infile(infile))
{
fclose(ifd);
/* process the specification file */
lb4fd = fopen(lb4file, "r");
if(lb4fd)
{
proc_4lb();
fclose(lb4fd);
} else {
puts("4lb: warning export file not found");
}
ofd = fopen(outfile, "w+b");
if(N_MAGIC(header) == OMAGIC)
aout_proc_outfile(ofd);
else
coff_proc_outfile(ofd);
fclose(ofd);
}
return 0;
}