ack/util/grind/rd.c

383 lines
7.6 KiB
C

/* $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 <stdio.h>
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 <stdio.h>
#include <alloc.h>
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