/* $Header$ */ /* a.out file reading ... */ #include "rd.h" #if defined(__sun) #define sun #endif #if defined(__i386) #define i386 #endif #if defined(__mc68020) #define mc68020 #endif #if defined(__sparc) #define sparc #endif #if defined(__vax) #define vax #endif #if defined(sun) || defined(vax) struct exec { #ifdef sun short a_x; unsigned short a_magic; #else unsigned long a_magic; #endif unsigned long a_text; unsigned long a_data; unsigned long a_bss; unsigned long a_syms; unsigned long a_entry; unsigned long a_trsize; unsigned long a_drsize; }; #define OMAGIC 0407 #define NMAGIC 0410 #define ZMAGIC 0413 #define N_BADMAG(x) \ ((x).a_magic!=OMAGIC && (x).a_magic!=NMAGIC && (x).a_magic!=ZMAGIC) #ifdef sun #define N_TXTOFF(x) ((x).a_magic == ZMAGIC ? 0 : sizeof(struct exec)) #else #define N_TXTOFF(x) (sizeof(struct exec)) #endif #define N_STROFF(x) (N_TXTOFF(x)+(x).a_text+(x).a_data+(x).a_trsize+(x).a_drsize+(x).a_syms) #ifdef sparc #define RELOC_SIZE 12 #else #define RELOC_SIZE 8 #endif struct nlist { union { char *n_name; long n_strx; } n_un; unsigned char n_type; char n_other; short n_desc; unsigned long n_value; }; #define N_UNDF 0 #define N_ABS 2 #define N_TEXT 4 #define N_DATA 6 #define N_BSS 8 #define N_FN 0x1e #define N_EXT 01 #define N_STAB 0xe0 #include static FILE *inf; static struct exec bh; static long seg_strings; static struct outhead hh; #define readf(a, b, c) (fread((char *)(a), (b), (int)(c), inf)) int rd_open(f) char *f; { if ((inf = fopen(f, "r")) == NULL) return 0; return 1; } rd_ohead(h) struct outhead *h; { if (! readf(&bh, sizeof(struct exec), 1)) rd_fatal(); if (N_BADMAG(bh)) rd_fatal(); h->oh_magic = O_CONVERTED; h->oh_stamp = 0; h->oh_nsect = 4; h->oh_nname = 3 + bh.a_syms / sizeof(struct nlist); h->oh_nrelo = (bh.a_trsize + bh.a_drsize) / RELOC_SIZE; h->oh_flags = h->oh_nrelo ? HF_LINK : 0; #if defined(sun) if (bh.a_magic == ZMAGIC) bh.a_text -= sizeof(struct exec); #endif h->oh_nemit = bh.a_text + bh.a_data; #if defined(sun) if (bh.a_magic == ZMAGIC) bh.a_text += sizeof(struct exec); #endif fseek(inf, N_STROFF(bh), 0); h->oh_nchar = getw(inf) + 6 + 6 + 5 - 4; /* ".text", ".data", ".bss", minus the size word */ seg_strings = h->oh_nchar - 17; fseek(inf, N_TXTOFF(bh)+bh.a_text+bh.a_data, 0); hh = *h; #if defined(sun) if (bh.a_magic == ZMAGIC) bh.a_text -= sizeof(struct exec); #endif } /*ARGSUSED1*/ rd_name(names, count) register struct outname *names; unsigned int count; /* ignored; complete namelist is read */ { names->on_valu = 0; names->on_foff = seg_strings + OFF_CHAR(hh); names->on_desc = 0; names->on_type = S_MIN | S_SCT; names++; names->on_valu = 0; names->on_foff = seg_strings + OFF_CHAR(hh) + 6; names->on_desc = 0; names->on_type = (S_MIN+2) | S_SCT; names++; names->on_valu = 0; names->on_foff = seg_strings + OFF_CHAR(hh) + 12; names->on_desc = 0; names->on_type = (S_MIN+3) | S_SCT; names++; count = bh.a_syms / sizeof(struct nlist); while (count > 0) { struct nlist n; if (! readf(&n, sizeof(struct nlist), 1)) rd_fatal(); count--; names->on_desc = n.n_desc; if (n.n_un.n_strx - 4 < 0) names->on_foff = 0; else names->on_foff = OFF_CHAR(hh) - 4 + n.n_un.n_strx; names->on_valu = n.n_value; if (n.n_type & N_STAB) { names->on_type = n.n_type << 8; names++; continue; } switch(n.n_type & ~N_EXT) { case N_ABS: names->on_type = S_ABS; break; case N_TEXT: names->on_type = S_MIN; break; case N_DATA: names->on_type = S_MIN + 2; names->on_valu -= bh.a_text; break; case N_BSS: names->on_type = S_MIN + 3; names->on_valu -= bh.a_text + bh.a_data; break; case N_UNDF: if (! names->on_valu) { names->on_type = S_UND; break; } names->on_type = (S_MIN + 3) | S_COM; break; case N_FN: names->on_type = S_FIL; break; default: rd_fatal(); } if (n.n_type & N_EXT) names->on_type |= S_EXT; names++; } } extern char *strcpy(); rd_string(strings, count) register char *strings; long count; { #if defined(sun) if (bh.a_magic == ZMAGIC) bh.a_text += sizeof(struct exec); #endif fseek(inf, N_STROFF(bh)+4, 0); if (! readf(strings, (int)count-17, 1)) rd_fatal(); strings += count-17; strcpy(strings, ".text"); strings += 6; strcpy(strings, ".data"); strings += 6; strcpy(strings, ".bss"); } rd_close() { fclose(inf); } #endif #if defined(i386) #include #include struct xexec { unsigned short x_magic; #define XMAGIC 01006 unsigned short x_ext; long x_text; long x_data; long x_bss; long x_syms; long x_reloc; long x_entry; char x_cpu; char x_relsym; unsigned short x_renv; }; struct xseg { unsigned short xs_type; unsigned short xs_attr; unsigned short xs_seg; unsigned short xs_sres; long xs_filpos; long xs_psize; long xs_vsize; long xs_rbase; long xs_lres; long xs_lres2; }; static FILE *inf; static struct outname *names; static char *strings; #define readf(a, b, c) (fread((char *)(a), (b), (int)(c), inf)) #define getshort(val, p) (val = (*p++ & 0377), val |= (*p++ & 0377) << 8) #define getlong(val, p) (val = (*p++ & 0377), \ val |= (*p++ & 0377) << 8, \ val |= (*p++ & 0377L) << 16, \ val |= (*p++ & 0377L) << 24) static get_names(h, sz) struct outhead *h; long sz; { register char *xnms = malloc((unsigned) sz); register char *p; register struct outname *onm = (struct outname *) malloc((((unsigned)sz+8)/9)*sizeof(struct outname)); struct xnm { unsigned short s_type, s_seg; long s_value; } xnm; if (xnms == 0 || onm == 0) No_Mem(); if (!readf(xnms, (unsigned) sz, 1)) rd_fatal(); names = onm; strings = p = xnms; while (sz > 0) { getshort(xnm.s_type, xnms); getshort(xnm.s_seg, xnms); getlong(xnm.s_value, xnms); onm->on_desc = 0; if (xnm.s_type & S_STB) { onm->on_type = xnm.s_type; onm->on_desc = xnm.s_seg; } else { switch(xnm.s_type & 0x1f) { case 0x1f: onm->on_type = S_FIL; break; case 0x8: onm->on_type = S_SCT; break; case 0: onm->on_type = S_UND; break; case 1: onm->on_type = S_ABS; break; default: onm->on_type = xnm.s_type & 0x1f; break; } } if (xnm.s_type & 0x20) onm->on_type |= S_EXT; onm->on_valu = xnm.s_value; sz -= 9; if (*xnms == '\0') { onm->on_foff = -1; xnms++; } else { onm->on_foff = p - strings; while (*p++ = *xnms++) sz--; } onm++; } h->oh_nname = onm - names; h->oh_nchar = p - strings; while (--onm >= names) { if (onm->on_foff == -1) onm->on_foff = 0; else onm->on_foff += OFF_CHAR(*h); } names = (struct outname *) realloc((char *) names, h->oh_nname * sizeof(struct outname)); strings = realloc(strings, (unsigned) h->oh_nchar); } int rd_open(f) char *f; { if ((inf = fopen(f, "r")) == NULL) return 0; return 1; } rd_ohead(h) struct outhead *h; { int sepid; struct xexec xhdr; struct xseg xseg[3]; if (! readf(&xhdr, sizeof(xhdr), 1)) rd_fatal(); if (xhdr.x_magic != XMAGIC) rd_fatal(); h->oh_magic = O_CONVERTED; h->oh_stamp = 0; h->oh_nsect = 4; h->oh_nrelo = 0; h->oh_flags = 0; h->oh_nemit = xhdr.x_text+xhdr.x_data; sepid = (xhdr.x_renv & 02) ? 1 : 0; fseek(inf, 0140L, 0); if (! readf(&xseg[0], sizeof(xseg[0]), sepid + 2)) rd_fatal(); fseek(inf, xseg[sepid+1].xs_filpos, 0); get_names(h, xhdr.x_syms); fclose(inf); } rd_name(nm, count) struct outname *nm; unsigned int count; { memcpy(nm, names, (int) count * sizeof(struct outname)); free((char *) names); } rd_string(nm, count) char *nm; long count; { memcpy(nm, strings, (int) count); free((char *) strings); } rd_close() { } #endif