Home | History | Annotate | Line # | Download | only in aout2hux
aout2hux.c revision 1.6
      1  1.1  itohy /*
      2  1.4  itohy  *	aout2hux - convert a.out/ELF executable to Human68k .x format
      3  1.1  itohy  *
      4  1.4  itohy  *	Read two a.out/ELF format executables with different load addresses
      5  1.1  itohy  *	and generate Human68k .x format executable.
      6  1.1  itohy  *
      7  1.1  itohy  *	written by Yasha (ITOH Yasufumi)
      8  1.1  itohy  *	public domain
      9  1.1  itohy  *
     10  1.1  itohy  * usage:
     11  1.1  itohy  *	aout2hux [ -o output.x ] a.out1 loadaddr1 a.out2 loadaddr2
     12  1.1  itohy  *
     13  1.4  itohy  *	The input files must be static OMAGIC/NMAGIC m68k a.out executables
     14  1.4  itohy  *	or m68k ELF executables.
     15  1.4  itohy  *	Two executables must have different loading addresses.
     16  1.1  itohy  *	Each of the load address must be a hexadecimal number.
     17  1.1  itohy  *	Load address shall be multiple of 4 for as / ld of NetBSD/m68k.
     18  1.1  itohy  *
     19  1.1  itohy  * example:
     20  1.4  itohy  *	% cc -N -static -Wl,-Ttext,0        -o aout1 *.o
     21  1.4  itohy  *	% cc -N -static -Wl,-Ttext,10203040 -o aout2 *.o
     22  1.1  itohy  *	% aout2hux -o foo.x aout1 0 aout2 10203040
     23  1.1  itohy  *
     24  1.6    dsl  *	$NetBSD: aout2hux.c,v 1.6 2009/03/14 14:46:07 dsl Exp $
     25  1.1  itohy  */
     26  1.1  itohy 
     27  1.1  itohy #include <sys/types.h>
     28  1.1  itohy #ifndef NO_UNISTD
     29  1.1  itohy # include <unistd.h>
     30  1.1  itohy #endif
     31  1.1  itohy #ifndef NO_STDLIB
     32  1.1  itohy # include <stdlib.h>
     33  1.1  itohy #endif
     34  1.1  itohy #include <stdio.h>
     35  1.1  itohy #include <string.h>
     36  1.1  itohy 
     37  1.1  itohy #include "type_local.h"
     38  1.1  itohy #include "aout68k.h"
     39  1.1  itohy #include "hux.h"
     40  1.1  itohy 
     41  1.4  itohy /* fseek() offset type */
     42  1.4  itohy typedef long	foff_t;
     43  1.4  itohy 
     44  1.1  itohy #ifndef DEFAULT_OUTPUT_FILE
     45  1.1  itohy # define DEFAULT_OUTPUT_FILE	"out.x"
     46  1.1  itohy #endif
     47  1.1  itohy 
     48  1.1  itohy #ifdef DEBUG
     49  1.1  itohy # define DPRINTF(x)	printf x
     50  1.1  itohy #else
     51  1.1  itohy # define DPRINTF(x)
     52  1.1  itohy #endif
     53  1.1  itohy 
     54  1.4  itohy struct exec_info {
     55  1.4  itohy 	foff_t		text_off;	/* file offset of text section */
     56  1.4  itohy 	foff_t		data_off;	/* file offset of data section */
     57  1.4  itohy 	u_int32_t	text_size;	/* size of text section */
     58  1.4  itohy 	u_int32_t	text_pad;	/* pad between text and data */
     59  1.4  itohy 	u_int32_t	data_size;	/* size of data section */
     60  1.4  itohy 	u_int32_t	bss_size;	/* size of bss */
     61  1.4  itohy 	u_int32_t	entry_addr;	/* entry point address */
     62  1.4  itohy };
     63  1.4  itohy 
     64  1.1  itohy unsigned get_uint16 PROTO((be_uint16_t *be));
     65  1.1  itohy u_int32_t get_uint32 PROTO((be_uint32_t *be));
     66  1.1  itohy void put_uint16 PROTO((be_uint16_t *be, unsigned v));
     67  1.1  itohy void put_uint32 PROTO((be_uint32_t *be, u_int32_t v));
     68  1.1  itohy void *do_realloc PROTO((void *p, size_t s));
     69  1.1  itohy 
     70  1.6    dsl static int open_aout(const char *fn, struct aout_m68k *hdr,
     71  1.6    dsl 		struct exec_info *inf);
     72  1.4  itohy static int open_elf PROTO((const char *fn, FILE *fp, struct elf_m68k_hdr *hdr,
     73  1.4  itohy 		struct exec_info *inf));
     74  1.4  itohy FILE *open_exec PROTO((const char *fn, struct exec_info *inf));
     75  1.4  itohy int check_2_exec_inf PROTO((struct exec_info *inf1, struct exec_info *inf2));
     76  1.1  itohy int aout2hux PROTO((const char *fn1, const char *fn2,
     77  1.1  itohy 		u_int32_t loadadr1, u_int32_t loadadr2, const char *fnx));
     78  1.1  itohy int gethex PROTO((u_int32_t *pval, const char *str));
     79  1.1  itohy void usage PROTO((const char *name));
     80  1.1  itohy int main PROTO((int argc, char *argv[]));
     81  1.1  itohy 
     82  1.1  itohy #if !defined(bzero) && defined(__SVR4)
     83  1.1  itohy # define bzero(d, n)	memset((d), 0, (n))
     84  1.1  itohy #endif
     85  1.1  itohy 
     86  1.1  itohy /*
     87  1.1  itohy  * read/write big-endian integer
     88  1.1  itohy  */
     89  1.1  itohy 
     90  1.1  itohy unsigned
     91  1.1  itohy get_uint16(be)
     92  1.1  itohy 	be_uint16_t *be;
     93  1.1  itohy {
     94  1.1  itohy 
     95  1.1  itohy 	return be->val[0] << 8 | be->val[1];
     96  1.1  itohy }
     97  1.1  itohy 
     98  1.1  itohy u_int32_t
     99  1.1  itohy get_uint32(be)
    100  1.1  itohy 	be_uint32_t *be;
    101  1.1  itohy {
    102  1.1  itohy 
    103  1.1  itohy 	return be->val[0]<<24 | be->val[1]<<16 | be->val[2]<<8 | be->val[3];
    104  1.1  itohy }
    105  1.1  itohy 
    106  1.1  itohy void
    107  1.1  itohy put_uint16(be, v)
    108  1.1  itohy 	be_uint16_t *be;
    109  1.1  itohy 	unsigned v;
    110  1.1  itohy {
    111  1.1  itohy 
    112  1.1  itohy 	be->val[0] = (u_int8_t) (v >> 8);
    113  1.1  itohy 	be->val[1] = (u_int8_t) v;
    114  1.1  itohy }
    115  1.1  itohy 
    116  1.1  itohy void
    117  1.1  itohy put_uint32(be, v)
    118  1.1  itohy 	be_uint32_t *be;
    119  1.1  itohy 	u_int32_t v;
    120  1.1  itohy {
    121  1.1  itohy 
    122  1.1  itohy 	be->val[0] = (u_int8_t) (v >> 24);
    123  1.1  itohy 	be->val[1] = (u_int8_t) (v >> 16);
    124  1.1  itohy 	be->val[2] = (u_int8_t) (v >> 8);
    125  1.1  itohy 	be->val[3] = (u_int8_t) v;
    126  1.1  itohy }
    127  1.1  itohy 
    128  1.1  itohy void *
    129  1.1  itohy do_realloc(p, s)
    130  1.1  itohy 	void *p;
    131  1.1  itohy 	size_t s;
    132  1.1  itohy {
    133  1.1  itohy 
    134  1.1  itohy 	p = p ? realloc(p, s) : malloc(s);	/* for portability */
    135  1.1  itohy 
    136  1.1  itohy 	if (!p) {
    137  1.1  itohy 		fprintf(stderr, "malloc failed\n");
    138  1.1  itohy 		exit(1);
    139  1.1  itohy 	}
    140  1.1  itohy 
    141  1.1  itohy 	return p;
    142  1.1  itohy }
    143  1.1  itohy 
    144  1.1  itohy /*
    145  1.4  itohy  * check a.out header
    146  1.4  itohy  */
    147  1.4  itohy static int
    148  1.4  itohy open_aout(fn, hdr, inf)
    149  1.4  itohy 	const char *fn;
    150  1.4  itohy 	struct aout_m68k *hdr;
    151  1.4  itohy 	struct exec_info *inf;
    152  1.4  itohy {
    153  1.4  itohy 	int i;
    154  1.4  itohy 
    155  1.4  itohy 	DPRINTF(("%s: is an a.out\n", fn));
    156  1.4  itohy 
    157  1.4  itohy 	if ((i = AOUT_GET_MID(hdr)) != AOUT_MID_M68K && i != AOUT_MID_M68K4K) {
    158  1.4  itohy 		fprintf(stderr, "%s: wrong architecture (mid %d)\n", fn, i);
    159  1.4  itohy 		return 1;
    160  1.4  itohy 	}
    161  1.4  itohy 
    162  1.4  itohy 	/* if unsolved relocations exist, not an executable but an object */
    163  1.4  itohy 	if (hdr->a_trsize.hostval || hdr->a_drsize.hostval) {
    164  1.4  itohy 		fprintf(stderr, "%s: not an executable (object file?)\n", fn);
    165  1.4  itohy 		return 1;
    166  1.4  itohy 	}
    167  1.4  itohy 
    168  1.4  itohy 	if (AOUT_GET_FLAGS(hdr) & (AOUT_FLAG_PIC | AOUT_FLAG_DYNAMIC)) {
    169  1.4  itohy 		fprintf(stderr, "%s: PIC and DYNAMIC are not supported\n", fn);
    170  1.4  itohy 		return 1;
    171  1.4  itohy 	}
    172  1.4  itohy 
    173  1.4  itohy 	inf->text_size = get_uint32(&hdr->a_text);
    174  1.4  itohy 	inf->data_size = get_uint32(&hdr->a_data);
    175  1.4  itohy 	inf->bss_size = get_uint32(&hdr->a_bss);
    176  1.4  itohy 	inf->entry_addr = get_uint32(&hdr->a_entry);
    177  1.4  itohy 	inf->text_off = sizeof(struct aout_m68k);
    178  1.4  itohy 	inf->data_off = sizeof(struct aout_m68k) + inf->text_size;
    179  1.4  itohy 	inf->text_pad = -inf->text_size & (AOUT_PAGESIZE(hdr) - 1);
    180  1.4  itohy 
    181  1.4  itohy 	return 0;
    182  1.4  itohy }
    183  1.4  itohy 
    184  1.4  itohy /*
    185  1.4  itohy  * digest ELF structure
    186  1.4  itohy  */
    187  1.4  itohy static int
    188  1.4  itohy open_elf(fn, fp, hdr, inf)
    189  1.4  itohy 	const char *fn;
    190  1.4  itohy 	FILE *fp;
    191  1.4  itohy 	struct elf_m68k_hdr *hdr;
    192  1.4  itohy 	struct exec_info *inf;
    193  1.4  itohy {
    194  1.4  itohy 	int i;
    195  1.4  itohy 	size_t nphdr;
    196  1.4  itohy 	struct elf_m68k_phdr phdr[2];
    197  1.4  itohy 
    198  1.4  itohy 	DPRINTF(("%s: is an ELF\n", fn));
    199  1.4  itohy 
    200  1.4  itohy 	if (hdr->e_ident[EI_VERSION] != EV_CURRENT ||
    201  1.4  itohy 	    get_uint32(&hdr->e_version) != EV_CURRENT) {
    202  1.4  itohy 		fprintf(stderr, "%s: unknown ELF version\n", fn);
    203  1.4  itohy 		return 1;
    204  1.4  itohy 	}
    205  1.4  itohy 
    206  1.5  itohy 	if (get_uint16(&hdr->e_type) != ET_EXEC) {
    207  1.4  itohy 		fprintf(stderr, "%s: not an executable\n", fn);
    208  1.4  itohy 		return 1;
    209  1.4  itohy 	}
    210  1.4  itohy 
    211  1.4  itohy 	if ((i = get_uint16(&hdr->e_machine)) != EM_68K) {
    212  1.4  itohy 		fprintf(stderr, "%s: wrong architecture (%d)\n", fn, i);
    213  1.4  itohy 		return 1;
    214  1.4  itohy 	}
    215  1.4  itohy 
    216  1.4  itohy 	if ((i = get_uint16(&hdr->e_shentsize)) != SIZE_ELF68K_SHDR) {
    217  1.4  itohy 		fprintf(stderr, "%s: size shdr %d should be %d\n", fn, i,
    218  1.4  itohy 			SIZE_ELF68K_SHDR);
    219  1.4  itohy 		return 1;
    220  1.4  itohy 	}
    221  1.4  itohy 
    222  1.4  itohy 	if ((i = get_uint16(&hdr->e_phentsize)) != SIZE_ELF68K_PHDR) {
    223  1.4  itohy 		fprintf(stderr, "%s: size phdr %d should be %d\n", fn, i,
    224  1.4  itohy 			SIZE_ELF68K_PHDR);
    225  1.4  itohy 		return 1;
    226  1.4  itohy 	}
    227  1.4  itohy 
    228  1.4  itohy 	if ((nphdr = get_uint16(&hdr->e_phnum)) != 1 && nphdr != 2) {
    229  1.4  itohy 		fprintf(stderr,
    230  1.4  itohy 			"%s: has %d loadable segments (should be 1 or 2)\n",
    231  1.4  itohy 			fn, nphdr);
    232  1.4  itohy 		return 1;
    233  1.4  itohy 	}
    234  1.4  itohy 
    235  1.4  itohy 	/* Read ELF program header table. */
    236  1.4  itohy 	if (fseek(fp, (foff_t) get_uint32(&hdr->e_phoff), SEEK_SET)) {
    237  1.4  itohy 		perror(fn);
    238  1.4  itohy 		return 1;
    239  1.4  itohy 	}
    240  1.4  itohy 	if (fread(phdr, sizeof phdr[0], nphdr, fp) != nphdr) {
    241  1.4  itohy 		fprintf(stderr, "%s: can't read ELF program header\n", fn);
    242  1.4  itohy 		return 1;
    243  1.4  itohy 	}
    244  1.4  itohy 
    245  1.4  itohy 	/* Just error checking. */
    246  1.4  itohy 	for (i = 0; i < (int) nphdr; i++) {
    247  1.4  itohy 		if (get_uint32(&phdr[i].p_type) != PT_LOAD) {
    248  1.4  itohy 			fprintf(stderr,
    249  1.4  itohy 				"%s: program header #%d is not loadable\n",
    250  1.4  itohy 				fn, i);
    251  1.4  itohy 			return 1;
    252  1.4  itohy 		}
    253  1.4  itohy 	}
    254  1.4  itohy 
    255  1.4  itohy 	if (nphdr == 1 && (get_uint32(&phdr[0].p_flags) & PF_W)) {
    256  1.4  itohy 		/*
    257  1.4  itohy 		 * Only one writable section --- probably "ld -N" executable.
    258  1.4  itohy 		 * Find out the start of data segment.
    259  1.4  itohy 		 */
    260  1.4  itohy 		struct elf_m68k_shdr shdr;
    261  1.4  itohy 		int nshdr;
    262  1.4  itohy 
    263  1.4  itohy 		nshdr = get_uint16(&hdr->e_shnum);
    264  1.4  itohy 
    265  1.4  itohy 		/* section #0 always exists and reserved --- skip */
    266  1.4  itohy 		if (nshdr > 1 &&
    267  1.4  itohy 		    fseek(fp,
    268  1.4  itohy 			  (foff_t) (get_uint32(&hdr->e_shoff) + sizeof shdr),
    269  1.4  itohy 			  SEEK_SET)) {
    270  1.4  itohy 			perror(fn);
    271  1.4  itohy 			return 1;
    272  1.4  itohy 		}
    273  1.4  itohy 		for (i = 1; i < nshdr; i++) {
    274  1.4  itohy 			if (fread(&shdr, sizeof shdr, 1, fp) != 1) {
    275  1.4  itohy 				fprintf(stderr,
    276  1.4  itohy 					"%s: can't read ELF section header\n",
    277  1.4  itohy 					fn);
    278  1.4  itohy 				return 1;
    279  1.4  itohy 			}
    280  1.4  itohy 
    281  1.4  itohy 			DPRINTF(("%s: section header #%d: flags 0x%x\n",
    282  1.4  itohy 				fn, i, get_uint32(&shdr.sh_flags)));
    283  1.4  itohy 
    284  1.4  itohy 			if (ELF68K_ISDATASEG(&shdr)) {
    285  1.4  itohy 				/*
    286  1.4  itohy 				 * data section is found.
    287  1.4  itohy 				 */
    288  1.4  itohy 				DPRINTF(("%s: one section, data found\n", fn));
    289  1.4  itohy 				inf->text_off = get_uint32(&phdr[0].p_offset);
    290  1.4  itohy 				inf->text_size = get_uint32(&shdr.sh_offset) -
    291  1.4  itohy 						 inf->text_off;
    292  1.4  itohy 				inf->text_pad = 0;
    293  1.4  itohy 				inf->data_off = inf->text_off + inf->text_size;
    294  1.4  itohy 				inf->data_size = get_uint32(&phdr[0].p_filesz) -
    295  1.4  itohy 						 inf->text_size;
    296  1.4  itohy 				inf->bss_size = get_uint32(&phdr[0].p_memsz) -
    297  1.4  itohy 						get_uint32(&phdr[0].p_filesz);
    298  1.4  itohy 				inf->entry_addr = get_uint32(&hdr->e_entry);
    299  1.4  itohy 				goto data_found;
    300  1.4  itohy 			}
    301  1.4  itohy 		}
    302  1.4  itohy 		/*
    303  1.4  itohy 		 * No data section found --- probably text + bss.
    304  1.4  itohy 		 */
    305  1.4  itohy 		DPRINTF(("%s: one section, no data section\n", fn));
    306  1.4  itohy 		inf->text_size = get_uint32(&phdr[0].p_filesz);
    307  1.4  itohy 		inf->data_size = 0;
    308  1.4  itohy 		inf->bss_size = get_uint32(&phdr[0].p_memsz) - inf->text_size;
    309  1.4  itohy 		inf->entry_addr = get_uint32(&hdr->e_entry);
    310  1.4  itohy 		inf->text_off = get_uint32(&phdr[0].p_offset);
    311  1.4  itohy 		inf->data_off = 0;
    312  1.4  itohy 		inf->text_pad = 0;
    313  1.4  itohy data_found:;
    314  1.4  itohy 	} else if (nphdr == 1) {
    315  1.4  itohy 		/*
    316  1.4  itohy 		 * Only one non-writable section --- pure text program?
    317  1.4  itohy 		 */
    318  1.4  itohy 		DPRINTF(("%s: one RO section\n", fn));
    319  1.4  itohy 		inf->text_size = get_uint32(&phdr[0].p_filesz);
    320  1.4  itohy 		inf->data_size = 0;
    321  1.4  itohy 		inf->bss_size = 0;
    322  1.4  itohy 		inf->entry_addr = get_uint32(&hdr->e_entry);
    323  1.4  itohy 		inf->text_off = get_uint32(&phdr[0].p_offset);
    324  1.4  itohy 		inf->data_off = 0;
    325  1.4  itohy 		inf->text_pad = get_uint32(&phdr[0].p_memsz) - inf->text_size;
    326  1.4  itohy 	} else {
    327  1.4  itohy 		/*
    328  1.4  itohy 		 * two sections
    329  1.4  itohy 		 * text + data assumed.
    330  1.4  itohy 		 */
    331  1.4  itohy 		int t = 0, d = 1, tmp;	/* first guess */
    332  1.4  itohy #define SWAP_T_D	tmp = t, t = d, d = tmp
    333  1.4  itohy 
    334  1.4  itohy 		DPRINTF(("%s: two sections\n", fn));
    335  1.4  itohy 
    336  1.4  itohy 		/* Find out text and data. */
    337  1.4  itohy 		if (get_uint32(&phdr[t].p_vaddr) > get_uint32(&phdr[d].p_vaddr))
    338  1.4  itohy 			SWAP_T_D;
    339  1.4  itohy 
    340  1.4  itohy 		if ((get_uint32(&phdr[t].p_flags) & PF_X) == 0 &&
    341  1.4  itohy 		    get_uint32(&phdr[d].p_flags) & PF_X)
    342  1.4  itohy 			SWAP_T_D;
    343  1.4  itohy 
    344  1.4  itohy 		if ((get_uint32(&phdr[d].p_flags) & PF_W) == 0 &&
    345  1.4  itohy 		    get_uint32(&phdr[t].p_flags) & PF_W)
    346  1.4  itohy 			SWAP_T_D;
    347  1.4  itohy #undef SWAP_T_D
    348  1.4  itohy 
    349  1.4  itohy 		/* Are the text/data sections correctly detected? */
    350  1.4  itohy 		if (get_uint32(&phdr[t].p_vaddr) >
    351  1.4  itohy 		    get_uint32(&phdr[d].p_vaddr)) {
    352  1.4  itohy 			fprintf(stderr, "%s: program sections not in order\n",
    353  1.4  itohy 				fn);
    354  1.4  itohy 			return 1;
    355  1.4  itohy 		}
    356  1.4  itohy 
    357  1.4  itohy 		if ((get_uint32(&phdr[t].p_flags) & PF_X) == 0)
    358  1.4  itohy 			fprintf(stderr, "%s: warning: text is not executable\n",
    359  1.4  itohy 				fn);
    360  1.4  itohy 
    361  1.4  itohy 		if ((get_uint32(&phdr[d].p_flags) & PF_W) == 0)
    362  1.4  itohy 			fprintf(stderr, "%s: warning: data is not writable\n",
    363  1.4  itohy 				fn);
    364  1.4  itohy 
    365  1.4  itohy 		inf->text_size = get_uint32(&phdr[t].p_filesz);
    366  1.4  itohy 		inf->data_size = get_uint32(&phdr[d].p_filesz);
    367  1.4  itohy 		inf->bss_size = get_uint32(&phdr[d].p_memsz) - inf->data_size;
    368  1.4  itohy 		inf->entry_addr = get_uint32(&hdr->e_entry);
    369  1.4  itohy 		inf->text_off = get_uint32(&phdr[t].p_offset);
    370  1.4  itohy 		inf->data_off = get_uint32(&phdr[d].p_offset);
    371  1.4  itohy 		inf->text_pad = get_uint32(&phdr[d].p_vaddr) -
    372  1.4  itohy 			(get_uint32(&phdr[t].p_vaddr) + inf->text_size);
    373  1.4  itohy 	}
    374  1.4  itohy 
    375  1.4  itohy 	return 0;
    376  1.4  itohy }
    377  1.4  itohy 
    378  1.4  itohy /*
    379  1.4  itohy  * open an executable
    380  1.1  itohy  */
    381  1.1  itohy FILE *
    382  1.4  itohy open_exec(fn, inf)
    383  1.1  itohy 	const char *fn;
    384  1.4  itohy 	struct exec_info *inf;
    385  1.1  itohy {
    386  1.1  itohy 	FILE *fp;
    387  1.1  itohy 	int i;
    388  1.4  itohy 	union {
    389  1.4  itohy 		struct aout_m68k	u_aout;
    390  1.4  itohy 		struct elf_m68k_hdr	u_elf;
    391  1.4  itohy 	} buf;
    392  1.4  itohy #define hdra	(&buf.u_aout)
    393  1.4  itohy #define hdre	(&buf.u_elf)
    394  1.1  itohy 
    395  1.1  itohy 	if (!(fp = fopen(fn, "r"))) {
    396  1.1  itohy 		perror(fn);
    397  1.1  itohy 		return (FILE *) NULL;
    398  1.1  itohy 	}
    399  1.4  itohy 
    400  1.4  itohy 	/*
    401  1.4  itohy 	 * Check for a.out.
    402  1.4  itohy 	 */
    403  1.4  itohy 
    404  1.4  itohy 	if (fread(hdra, sizeof(struct aout_m68k), 1, fp) != 1) {
    405  1.1  itohy 		fprintf(stderr, "%s: can't read a.out header\n", fn);
    406  1.1  itohy 		goto out;
    407  1.1  itohy 	}
    408  1.1  itohy 
    409  1.4  itohy 	if ((i = AOUT_GET_MAGIC(hdra)) != AOUT_OMAGIC && i != AOUT_NMAGIC)
    410  1.4  itohy 		goto notaout;
    411  1.4  itohy 
    412  1.4  itohy 	if (open_aout(fn, hdra, inf))
    413  1.1  itohy 		goto out;
    414  1.1  itohy 
    415  1.4  itohy 	/* OK! */
    416  1.4  itohy 	return fp;
    417  1.4  itohy 
    418  1.4  itohy notaout:
    419  1.4  itohy 	/*
    420  1.4  itohy 	 * Check for ELF.
    421  1.4  itohy 	 */
    422  1.4  itohy 
    423  1.4  itohy 	if (hdre->e_ident[EI_MAG0] != ELFMAG0 ||
    424  1.4  itohy 	    hdre->e_ident[EI_MAG1] != ELFMAG1 ||
    425  1.4  itohy 	    hdre->e_ident[EI_MAG2] != ELFMAG2 ||
    426  1.4  itohy 	    hdre->e_ident[EI_MAG3] != ELFMAG3 ||
    427  1.4  itohy 	    hdre->e_ident[EI_CLASS] != ELFCLASS32 ||
    428  1.4  itohy 	    hdre->e_ident[EI_DATA] != ELFDATA2MSB) {
    429  1.4  itohy 		fprintf(stderr,
    430  1.4  itohy 		    "%s: not an OMAGIC or NMAGIC a.out, or a 32bit BE ELF\n",
    431  1.4  itohy 		    fn);
    432  1.1  itohy 		goto out;
    433  1.1  itohy 	}
    434  1.1  itohy 
    435  1.4  itohy 	/* ELF header is longer than a.out header.  Read the rest. */
    436  1.4  itohy 	if (fread(hdra + 1,
    437  1.4  itohy 		  sizeof(struct elf_m68k_hdr) - sizeof(struct aout_m68k),
    438  1.4  itohy 		  1, fp) != 1) {
    439  1.4  itohy 		fprintf(stderr, "%s: can't read ELF header\n", fn);
    440  1.1  itohy 		goto out;
    441  1.1  itohy 	}
    442  1.1  itohy 
    443  1.4  itohy 	if (open_elf(fn, fp, hdre, inf))
    444  1.1  itohy 		goto out;
    445  1.1  itohy 
    446  1.1  itohy 	/* OK! */
    447  1.1  itohy 	return fp;
    448  1.1  itohy 
    449  1.1  itohy out:	fclose(fp);
    450  1.1  itohy 	return (FILE *) NULL;
    451  1.4  itohy #undef hdra
    452  1.4  itohy #undef hdre
    453  1.1  itohy }
    454  1.1  itohy 
    455  1.1  itohy /*
    456  1.4  itohy  * compare two executables and check if they are compatible
    457  1.1  itohy  */
    458  1.1  itohy int
    459  1.4  itohy check_2_exec_inf(inf1, inf2)
    460  1.4  itohy 	struct exec_info *inf1, *inf2;
    461  1.1  itohy {
    462  1.1  itohy 
    463  1.4  itohy 	if (inf1->text_size != inf2->text_size ||
    464  1.4  itohy 	    inf1->text_pad != inf2->text_pad ||
    465  1.4  itohy 	    inf1->data_size != inf2->data_size ||
    466  1.4  itohy 	    inf1->bss_size != inf2->bss_size)
    467  1.1  itohy 		return -1;
    468  1.1  itohy 
    469  1.1  itohy 	return 0;
    470  1.1  itohy }
    471  1.1  itohy 
    472  1.1  itohy /* allocation unit (in bytes) of relocation table */
    473  1.1  itohy #define RELTBL_CHUNK	8192
    474  1.1  itohy 
    475  1.1  itohy /*
    476  1.1  itohy  * add an entry to the relocation table
    477  1.1  itohy  */
    478  1.1  itohy #define ADD_RELTBL(adr)	\
    479  1.1  itohy 	if (relsize + sizeof(struct relinf_l) > relallocsize)		    \
    480  1.1  itohy 		reltbl = do_realloc(reltbl, relallocsize += RELTBL_CHUNK);  \
    481  1.1  itohy 	if ((adr) < reladdr + HUX_MINLREL) {				    \
    482  1.1  itohy 		struct relinf_s *r = (struct relinf_s *)(reltbl + relsize); \
    483  1.1  itohy 		put_uint16(&r->locoff_s, (unsigned)((adr) - reladdr));	    \
    484  1.1  itohy 		relsize += sizeof(struct relinf_s);			    \
    485  1.1  itohy 		DPRINTF(("short"));					    \
    486  1.1  itohy 	} else {							    \
    487  1.1  itohy 		struct relinf_l *r = (struct relinf_l *)(reltbl + relsize); \
    488  1.1  itohy 		put_uint16(&r->lrelmag, HUXLRELMAGIC);			    \
    489  1.1  itohy 		put_uint32((be_uint32_t *)r->locoff_l, (adr) - reladdr);    \
    490  1.1  itohy 		relsize += sizeof(struct relinf_l);			    \
    491  1.1  itohy 		DPRINTF(("long "));					    \
    492  1.1  itohy 	}								    \
    493  1.1  itohy 	DPRINTF((" reloc 0x%06x", (adr)));				    \
    494  1.1  itohy 	reladdr = (adr);
    495  1.1  itohy 
    496  1.1  itohy #define ERR1	{ if (ferror(fpa1)) perror(fn1);			\
    497  1.1  itohy 		  else fprintf(stderr, "%s: unexpected EOF\n", fn1);	\
    498  1.1  itohy 		  goto out; }
    499  1.1  itohy #define ERR2	{ if (ferror(fpa2)) perror(fn2);			\
    500  1.1  itohy 		  else fprintf(stderr, "%s: unexpected EOF\n", fn2);	\
    501  1.1  itohy 		  goto out; }
    502  1.1  itohy #define ERRC	{ fprintf(stderr, "files %s and %s are inconsistent\n",	\
    503  1.1  itohy 				  fn1, fn2);				\
    504  1.1  itohy 		  goto out; }
    505  1.1  itohy 
    506  1.1  itohy /*
    507  1.4  itohy  * read input executables and output .x body
    508  1.1  itohy  * and create relocation table
    509  1.1  itohy  */
    510  1.1  itohy #define CREATE_RELOCATION(segsize)	\
    511  1.1  itohy 	while (segsize > 0 || nbuf) {					\
    512  1.1  itohy 		if (nbuf == 0) {					\
    513  1.1  itohy 			if (fread(&b1.half[0], SIZE_16, 1, fpa1) != 1)	\
    514  1.1  itohy 				ERR1					\
    515  1.1  itohy 			if (fread(&b2.half[0], SIZE_16, 1, fpa2) != 1)	\
    516  1.1  itohy 				ERR2					\
    517  1.1  itohy 			nbuf = 1;					\
    518  1.1  itohy 			segsize -= SIZE_16;				\
    519  1.1  itohy 		} else if (nbuf == 1) {					\
    520  1.1  itohy 			if (segsize == 0) {				\
    521  1.1  itohy 				if (b1.half[0].hostval != b2.half[0].hostval) \
    522  1.1  itohy 					ERRC				\
    523  1.1  itohy 				fwrite(&b1.half[0], SIZE_16, 1, fpx);	\
    524  1.1  itohy 				nbuf = 0;				\
    525  1.1  itohy 				addr += SIZE_16;			\
    526  1.1  itohy 			} else {					\
    527  1.1  itohy 				if (fread(&b1.half[1], SIZE_16, 1, fpa1) != 1)\
    528  1.1  itohy 					ERR1				\
    529  1.1  itohy 				if (fread(&b2.half[1], SIZE_16, 1, fpa2) != 1)\
    530  1.1  itohy 					ERR2				\
    531  1.1  itohy 				nbuf = 2;				\
    532  1.1  itohy 				segsize -= SIZE_16;			\
    533  1.1  itohy 			}						\
    534  1.1  itohy 		} else /* if (nbuf == 2) */ {				\
    535  1.1  itohy 			if (b1.hostval != b2.hostval &&			\
    536  1.1  itohy 			    get_uint32(&b1) - loadadr1			\
    537  1.1  itohy 					== get_uint32(&b2) - loadadr2) {\
    538  1.1  itohy 				/* do relocation */			\
    539  1.1  itohy 				ADD_RELTBL(addr)			\
    540  1.1  itohy 									\
    541  1.1  itohy 				put_uint32(&b1, get_uint32(&b1) - loadadr1);  \
    542  1.1  itohy 				DPRINTF((" v 0x%08x\t", get_uint32(&b1)));    \
    543  1.1  itohy 				fwrite(&b1, SIZE_32, 1, fpx);		\
    544  1.1  itohy 				nbuf = 0;				\
    545  1.1  itohy 				addr += SIZE_32;			\
    546  1.1  itohy 			} else if (b1.half[0].hostval == b2.half[0].hostval) {\
    547  1.1  itohy 				fwrite(&b1.half[0], SIZE_16, 1, fpx);	\
    548  1.1  itohy 				addr += SIZE_16;			\
    549  1.1  itohy 				b1.half[0] = b1.half[1];		\
    550  1.1  itohy 				b2.half[0] = b2.half[1];		\
    551  1.1  itohy 				nbuf = 1;				\
    552  1.1  itohy 			} else						\
    553  1.1  itohy 				ERRC					\
    554  1.1  itohy 		}							\
    555  1.1  itohy 	}
    556  1.1  itohy 
    557  1.1  itohy int
    558  1.1  itohy aout2hux(fn1, fn2, loadadr1, loadadr2, fnx)
    559  1.1  itohy 	const char *fn1, *fn2, *fnx;
    560  1.1  itohy 	u_int32_t loadadr1, loadadr2;
    561  1.1  itohy {
    562  1.1  itohy 	int status = 1;			/* the default is "failed" */
    563  1.1  itohy 	FILE *fpa1 = NULL, *fpa2 = NULL;
    564  1.4  itohy 	struct exec_info inf1, inf2;
    565  1.1  itohy 	FILE *fpx = NULL;
    566  1.1  itohy 	struct huxhdr xhdr;
    567  1.4  itohy 	u_int32_t textsize, datasize, paddingsize, execoff;
    568  1.1  itohy 
    569  1.1  itohy 	/* for relocation */
    570  1.1  itohy 	be_uint32_t b1, b2;
    571  1.1  itohy 	int nbuf;
    572  1.1  itohy 	u_int32_t addr;
    573  1.1  itohy 
    574  1.1  itohy 	/* for relocation table */
    575  1.1  itohy 	size_t relsize, relallocsize;
    576  1.1  itohy 	u_int32_t reladdr;
    577  1.1  itohy 	char *reltbl = NULL;
    578  1.1  itohy 
    579  1.1  itohy 
    580  1.1  itohy 	/*
    581  1.1  itohy 	 * check load addresses
    582  1.1  itohy 	 */
    583  1.1  itohy 	if (loadadr1 == loadadr2) {
    584  1.1  itohy 		fprintf(stderr, "two load addresses must be different\n");
    585  1.1  itohy 		return 1;
    586  1.1  itohy 	}
    587  1.1  itohy 
    588  1.1  itohy 	/*
    589  1.4  itohy 	 * open input executables and check them
    590  1.1  itohy 	 */
    591  1.4  itohy 	if (!(fpa1 = open_exec(fn1, &inf1)) || !(fpa2 = open_exec(fn2, &inf2)))
    592  1.1  itohy 		goto out;
    593  1.1  itohy 
    594  1.1  itohy 	/*
    595  1.1  itohy 	 * check for consistency
    596  1.1  itohy 	 */
    597  1.4  itohy 	if (check_2_exec_inf(&inf1, &inf2)) {
    598  1.1  itohy 		fprintf(stderr, "files %s and %s are incompatible\n",
    599  1.1  itohy 				fn1, fn2);
    600  1.1  itohy 		goto out;
    601  1.1  itohy 	}
    602  1.1  itohy 	/* check entry address */
    603  1.4  itohy 	if (inf1.entry_addr - loadadr1 != inf2.entry_addr - loadadr2) {
    604  1.1  itohy 		fprintf(stderr, "address of %s or %s may be incorrect\n",
    605  1.1  itohy 				fn1, fn2);
    606  1.1  itohy 		goto out;
    607  1.1  itohy 	}
    608  1.1  itohy 
    609  1.1  itohy 	/*
    610  1.4  itohy 	 * get information of the executables
    611  1.1  itohy 	 */
    612  1.4  itohy 	textsize = inf1.text_size;
    613  1.4  itohy 	paddingsize = inf1.text_pad;
    614  1.4  itohy 	datasize = inf1.data_size;
    615  1.4  itohy 	execoff = inf1.entry_addr - loadadr1;
    616  1.4  itohy 
    617  1.4  itohy 	DPRINTF(("text: %u, data: %u, pad: %u, bss: %u, exec: %u\n",
    618  1.4  itohy 		textsize, datasize, paddingsize, inf1.bss_size, execoff));
    619  1.1  itohy 
    620  1.1  itohy 	if (textsize & 1) {
    621  1.1  itohy 		fprintf(stderr, "text size is not even\n");
    622  1.1  itohy 		goto out;
    623  1.1  itohy 	}
    624  1.1  itohy 	if (datasize & 1) {
    625  1.1  itohy 		fprintf(stderr, "data size is not even\n");
    626  1.1  itohy 		goto out;
    627  1.1  itohy 	}
    628  1.1  itohy 	if (execoff >= textsize &&
    629  1.1  itohy 	    (execoff < textsize + paddingsize ||
    630  1.1  itohy 	     execoff >= textsize + paddingsize + datasize)) {
    631  1.1  itohy 		fprintf(stderr, "exec addr is not in text or data segment\n");
    632  1.1  itohy 		goto out;
    633  1.1  itohy 	}
    634  1.1  itohy 
    635  1.1  itohy 	/*
    636  1.1  itohy 	 * prepare for .x header
    637  1.1  itohy 	 */
    638  1.1  itohy 	bzero((void *) &xhdr, sizeof xhdr);
    639  1.1  itohy 	put_uint16(&xhdr.x_magic, HUXMAGIC);
    640  1.1  itohy 	put_uint32(&xhdr.x_entry, execoff);
    641  1.1  itohy 	put_uint32(&xhdr.x_text, textsize + paddingsize);
    642  1.4  itohy 	put_uint32(&xhdr.x_data, inf1.data_size);
    643  1.4  itohy 	put_uint32(&xhdr.x_bss, inf1.bss_size);
    644  1.1  itohy 
    645  1.1  itohy 	/*
    646  1.1  itohy 	 * create output file
    647  1.1  itohy 	 */
    648  1.1  itohy 	if (!(fpx = fopen(fnx, "w")) ||
    649  1.4  itohy 	    fseek(fpx, (foff_t) sizeof xhdr, SEEK_SET)) { /* skip header */
    650  1.1  itohy 		perror(fnx);
    651  1.1  itohy 		goto out;
    652  1.1  itohy 	}
    653  1.1  itohy 
    654  1.1  itohy 	addr = 0;
    655  1.1  itohy 	nbuf = 0;
    656  1.1  itohy 
    657  1.1  itohy 	relsize = relallocsize = 0;
    658  1.1  itohy 	reladdr = 0;
    659  1.1  itohy 
    660  1.1  itohy 	/*
    661  1.1  itohy 	 * text segment
    662  1.1  itohy 	 */
    663  1.4  itohy 	if (fseek(fpa1, inf1.text_off, SEEK_SET)) {
    664  1.4  itohy 		perror(fn1);
    665  1.4  itohy 		goto out;
    666  1.4  itohy 	}
    667  1.4  itohy 	if (fseek(fpa2, inf2.text_off, SEEK_SET)) {
    668  1.4  itohy 		perror(fn2);
    669  1.4  itohy 		goto out;
    670  1.4  itohy 	}
    671  1.1  itohy 	CREATE_RELOCATION(textsize)
    672  1.1  itohy 
    673  1.1  itohy 	/*
    674  1.1  itohy 	 * page boundary
    675  1.1  itohy 	 */
    676  1.1  itohy 	addr += paddingsize;
    677  1.1  itohy 	while (paddingsize--)
    678  1.1  itohy 		putc('\0', fpx);
    679  1.1  itohy 
    680  1.1  itohy 	/*
    681  1.1  itohy 	 * data segment
    682  1.1  itohy 	 */
    683  1.4  itohy 	if (fseek(fpa1, inf1.data_off, SEEK_SET)) {
    684  1.4  itohy 		perror(fn1);
    685  1.4  itohy 		goto out;
    686  1.4  itohy 	}
    687  1.4  itohy 	if (fseek(fpa2, inf2.data_off, SEEK_SET)) {
    688  1.4  itohy 		perror(fn2);
    689  1.4  itohy 		goto out;
    690  1.4  itohy 	}
    691  1.1  itohy 	CREATE_RELOCATION(datasize)
    692  1.1  itohy 
    693  1.1  itohy 	/*
    694  1.1  itohy 	 * error check of the above
    695  1.1  itohy 	 */
    696  1.1  itohy 	if (ferror(fpx)) {
    697  1.1  itohy 		fprintf(stderr, "%s: write failure\n", fnx);
    698  1.1  itohy 		goto out;
    699  1.1  itohy 	}
    700  1.1  itohy 
    701  1.1  itohy 	/*
    702  1.1  itohy 	 * write relocation table
    703  1.1  itohy 	 */
    704  1.1  itohy 	if (relsize > 0) {
    705  1.1  itohy 		DPRINTF(("\n"));
    706  1.1  itohy 		if (fwrite(reltbl, 1, relsize, fpx) != relsize) {
    707  1.1  itohy 			perror(fnx);
    708  1.1  itohy 			goto out;
    709  1.1  itohy 		}
    710  1.1  itohy 	}
    711  1.1  itohy 
    712  1.1  itohy 	/*
    713  1.1  itohy 	 * write .x header at the top of the output file
    714  1.1  itohy 	 */
    715  1.1  itohy 	put_uint32(&xhdr.x_rsize, relsize);
    716  1.4  itohy 	if (fseek(fpx, (foff_t) 0, SEEK_SET) ||
    717  1.1  itohy 	    fwrite(&xhdr, sizeof xhdr, 1, fpx) != 1) {
    718  1.1  itohy 		perror(fnx);
    719  1.1  itohy 		goto out;
    720  1.1  itohy 	}
    721  1.1  itohy 
    722  1.1  itohy 	status = 0;	/* all OK */
    723  1.1  itohy 
    724  1.1  itohy out:	/*
    725  1.1  itohy 	 * cleanup
    726  1.1  itohy 	 */
    727  1.1  itohy 	if (fpa1)
    728  1.1  itohy 		fclose(fpa1);
    729  1.1  itohy 	if (fpa2)
    730  1.1  itohy 		fclose(fpa2);
    731  1.1  itohy 	if (fpx) {
    732  1.1  itohy 		if (fclose(fpx) && status == 0) {
    733  1.1  itohy 			/* Alas, final flush failed! */
    734  1.1  itohy 			perror(fnx);
    735  1.1  itohy 			status = 1;
    736  1.1  itohy 		}
    737  1.1  itohy 		if (status)
    738  1.1  itohy 			remove(fnx);
    739  1.1  itohy 	}
    740  1.1  itohy 	if (reltbl)
    741  1.1  itohy 		free(reltbl);
    742  1.1  itohy 
    743  1.1  itohy 	return status;
    744  1.1  itohy }
    745  1.1  itohy 
    746  1.1  itohy #ifndef NO_BIST
    747  1.1  itohy void bist PROTO((void));
    748  1.1  itohy 
    749  1.1  itohy /*
    750  1.1  itohy  * built-in self test
    751  1.1  itohy  */
    752  1.1  itohy void
    753  1.1  itohy bist()
    754  1.1  itohy {
    755  1.1  itohy 	be_uint16_t be16;
    756  1.1  itohy 	be_uint32_t be32;
    757  1.1  itohy 	be_uint32_t be32x2[2];
    758  1.1  itohy 
    759  1.1  itohy 	be16.val[0] = 0x12; be16.val[1] = 0x34;
    760  1.1  itohy 	be32.val[0] = 0xfe; be32.val[1] = 0xdc;
    761  1.1  itohy 	be32.val[2] = 0xba; be32.val[3] = 0x98;
    762  1.1  itohy 
    763  1.1  itohy 	put_uint16(&be32x2[0].half[1], 0x4567);
    764  1.1  itohy 	put_uint32(&be32x2[1], 0xa9876543);
    765  1.1  itohy 
    766  1.1  itohy 	if (sizeof(u_int8_t) != 1 || sizeof(u_int16_t) != 2 ||
    767  1.1  itohy 	    sizeof(u_int32_t) != 4 ||
    768  1.1  itohy 	    SIZE_16 != 2 || SIZE_32 != 4 || sizeof be32x2 != 8 ||
    769  1.1  itohy 	    sizeof(struct relinf_s) != 2 || sizeof(struct relinf_l) != 6 ||
    770  1.4  itohy 	    SIZE_ELF68K_HDR != 52 || SIZE_ELF68K_SHDR != 40 ||
    771  1.4  itohy 	    SIZE_ELF68K_PHDR != 32 ||
    772  1.1  itohy 	    get_uint16(&be16) != 0x1234 || get_uint32(&be32) != 0xfedcba98 ||
    773  1.1  itohy 	    get_uint16(&be32x2[0].half[1]) != 0x4567 ||
    774  1.1  itohy 	    get_uint32(&be32x2[1]) != 0xa9876543) {
    775  1.1  itohy 		fprintf(stderr, "BIST failed\n");
    776  1.1  itohy 		exit(1);
    777  1.1  itohy 	}
    778  1.1  itohy }
    779  1.1  itohy #endif
    780  1.1  itohy 
    781  1.1  itohy int
    782  1.1  itohy gethex(pval, str)
    783  1.1  itohy 	u_int32_t *pval;
    784  1.1  itohy 	const char *str;
    785  1.1  itohy {
    786  1.1  itohy 	const unsigned char *p = (const unsigned char *) str;
    787  1.1  itohy 	u_int32_t val;
    788  1.1  itohy 	int over;
    789  1.1  itohy 
    790  1.1  itohy 	/* skip leading "0x" if exists */
    791  1.1  itohy 	if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
    792  1.1  itohy 		p += 2;
    793  1.1  itohy 
    794  1.1  itohy 	if (!*p)
    795  1.1  itohy 		goto bad;
    796  1.1  itohy 
    797  1.1  itohy 	for (val = 0, over = 0; *p; p++) {
    798  1.1  itohy 		int digit;
    799  1.1  itohy 
    800  1.1  itohy 		switch (*p) {
    801  1.1  itohy 		case '0': case '1': case '2': case '3': case '4':
    802  1.1  itohy 		case '5': case '6': case '7': case '8': case '9':
    803  1.1  itohy 			digit = *p - '0';
    804  1.1  itohy 			break;
    805  1.1  itohy 		case 'a': case 'A':	digit = 10; break;
    806  1.1  itohy 		case 'b': case 'B':	digit = 11; break;
    807  1.1  itohy 		case 'c': case 'C':	digit = 12; break;
    808  1.1  itohy 		case 'd': case 'D':	digit = 13; break;
    809  1.1  itohy 		case 'e': case 'E':	digit = 14; break;
    810  1.1  itohy 		case 'f': case 'F':	digit = 15; break;
    811  1.1  itohy 		default:
    812  1.1  itohy 			goto bad;
    813  1.1  itohy 		}
    814  1.4  itohy 		if (val >= 0x10000000)
    815  1.1  itohy 			over = 1;
    816  1.1  itohy 		val = (val << 4) | digit;
    817  1.1  itohy 	}
    818  1.1  itohy 
    819  1.1  itohy 	if (over)
    820  1.1  itohy 		fprintf(stderr, "warning: %s: constant overflow\n", str);
    821  1.1  itohy 
    822  1.1  itohy 	*pval = val;
    823  1.1  itohy 
    824  1.1  itohy 	DPRINTF(("gethex: %s -> 0x%x\n", str, val));
    825  1.1  itohy 
    826  1.1  itohy 	return 0;
    827  1.1  itohy 
    828  1.1  itohy bad:
    829  1.1  itohy 	fprintf(stderr, "%s: not a hexadecimal number\n", str);
    830  1.1  itohy 	return 1;
    831  1.1  itohy }
    832  1.1  itohy 
    833  1.1  itohy void
    834  1.1  itohy usage(name)
    835  1.1  itohy 	const char *name;
    836  1.1  itohy {
    837  1.1  itohy 
    838  1.1  itohy 	fprintf(stderr, "\
    839  1.1  itohy usage: %s [ -o output.x ] a.out1 loadaddr1 a.out2 loadaddr2\n\n\
    840  1.4  itohy The input files must be static OMAGIC/NMAGIC m68k a.out executables\n\
    841  1.4  itohy or m68k ELF executables.\n\
    842  1.4  itohy Two executables must have different loading addresses.\n\
    843  1.1  itohy Each of the load address must be a hexadecimal number.\n\
    844  1.1  itohy The default output filename is \"%s\".\n" ,name, DEFAULT_OUTPUT_FILE);
    845  1.1  itohy 
    846  1.1  itohy 	exit(1);
    847  1.1  itohy }
    848  1.1  itohy 
    849  1.1  itohy int
    850  1.1  itohy main(argc, argv)
    851  1.1  itohy 	int argc;
    852  1.1  itohy 	char *argv[];
    853  1.1  itohy {
    854  1.1  itohy 	const char *outfile = DEFAULT_OUTPUT_FILE;
    855  1.1  itohy 	u_int32_t adr1, adr2;
    856  1.1  itohy 
    857  1.1  itohy #ifndef NO_BIST
    858  1.1  itohy 	bist();
    859  1.1  itohy #endif
    860  1.1  itohy 
    861  1.1  itohy 	if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'o' && !argv[1][2]) {
    862  1.1  itohy 		outfile = argv[2];
    863  1.1  itohy 		argv += 2;
    864  1.1  itohy 		argc -= 2;
    865  1.1  itohy 	}
    866  1.1  itohy 
    867  1.1  itohy 	if (argc != 5)
    868  1.1  itohy 		usage(argv[0]);
    869  1.1  itohy 
    870  1.1  itohy 	if (gethex(&adr1, argv[2]) || gethex(&adr2, argv[4]))
    871  1.1  itohy 		usage(argv[0]);
    872  1.1  itohy 
    873  1.1  itohy 	return aout2hux(argv[1], argv[3], adr1, adr2, outfile);
    874  1.1  itohy }
    875