Home | History | Annotate | Line # | Download | only in aout2hux
aout2hux.c revision 1.3.14.1
      1       1.1     itohy /*
      2  1.3.14.1  wrstuden  *	aout2hux - convert a.out/ELF executable to Human68k .x format
      3       1.1     itohy  *
      4  1.3.14.1  wrstuden  *	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.3.14.1  wrstuden  *	The input files must be static OMAGIC/NMAGIC m68k a.out executables
     14  1.3.14.1  wrstuden  *	or m68k ELF executables.
     15  1.3.14.1  wrstuden  *	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.3.14.1  wrstuden  *	% cc -N -static -Wl,-Ttext,0        -o aout1 *.o
     21  1.3.14.1  wrstuden  *	% 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.3.14.1  wrstuden  *	$NetBSD: aout2hux.c,v 1.3.14.1 1999/12/27 18:34:17 wrstuden 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.3.14.1  wrstuden /* fseek() offset type */
     42  1.3.14.1  wrstuden typedef long	foff_t;
     43  1.3.14.1  wrstuden 
     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.3.14.1  wrstuden struct exec_info {
     55  1.3.14.1  wrstuden 	foff_t		text_off;	/* file offset of text section */
     56  1.3.14.1  wrstuden 	foff_t		data_off;	/* file offset of data section */
     57  1.3.14.1  wrstuden 	u_int32_t	text_size;	/* size of text section */
     58  1.3.14.1  wrstuden 	u_int32_t	text_pad;	/* pad between text and data */
     59  1.3.14.1  wrstuden 	u_int32_t	data_size;	/* size of data section */
     60  1.3.14.1  wrstuden 	u_int32_t	bss_size;	/* size of bss */
     61  1.3.14.1  wrstuden 	u_int32_t	entry_addr;	/* entry point address */
     62  1.3.14.1  wrstuden };
     63  1.3.14.1  wrstuden 
     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.3.14.1  wrstuden static int open_aout __P((const char *fn, struct aout_m68k *hdr,
     71  1.3.14.1  wrstuden 		struct exec_info *inf));
     72  1.3.14.1  wrstuden static int open_elf PROTO((const char *fn, FILE *fp, struct elf_m68k_hdr *hdr,
     73  1.3.14.1  wrstuden 		struct exec_info *inf));
     74  1.3.14.1  wrstuden FILE *open_exec PROTO((const char *fn, struct exec_info *inf));
     75  1.3.14.1  wrstuden 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.3.14.1  wrstuden  * check a.out header
    146       1.1     itohy  */
    147  1.3.14.1  wrstuden static int
    148  1.3.14.1  wrstuden open_aout(fn, hdr, inf)
    149       1.1     itohy 	const char *fn;
    150       1.1     itohy 	struct aout_m68k *hdr;
    151  1.3.14.1  wrstuden 	struct exec_info *inf;
    152  1.3.14.1  wrstuden {
    153  1.3.14.1  wrstuden 	int i;
    154  1.3.14.1  wrstuden 
    155  1.3.14.1  wrstuden 	DPRINTF(("%s: is an a.out\n", fn));
    156  1.3.14.1  wrstuden 
    157  1.3.14.1  wrstuden 	if ((i = AOUT_GET_MID(hdr)) != AOUT_MID_M68K && i != AOUT_MID_M68K4K) {
    158  1.3.14.1  wrstuden 		fprintf(stderr, "%s: wrong architecture (mid %d)\n", fn, i);
    159  1.3.14.1  wrstuden 		return 1;
    160  1.3.14.1  wrstuden 	}
    161  1.3.14.1  wrstuden 
    162  1.3.14.1  wrstuden 	/* if unsolved relocations exist, not an executable but an object */
    163  1.3.14.1  wrstuden 	if (hdr->a_trsize.hostval || hdr->a_drsize.hostval) {
    164  1.3.14.1  wrstuden 		fprintf(stderr, "%s: not an executable (object file?)\n", fn);
    165  1.3.14.1  wrstuden 		return 1;
    166  1.3.14.1  wrstuden 	}
    167  1.3.14.1  wrstuden 
    168  1.3.14.1  wrstuden 	if (AOUT_GET_FLAGS(hdr) & (AOUT_FLAG_PIC | AOUT_FLAG_DYNAMIC)) {
    169  1.3.14.1  wrstuden 		fprintf(stderr, "%s: PIC and DYNAMIC are not supported\n", fn);
    170  1.3.14.1  wrstuden 		return 1;
    171  1.3.14.1  wrstuden 	}
    172  1.3.14.1  wrstuden 
    173  1.3.14.1  wrstuden 	inf->text_size = get_uint32(&hdr->a_text);
    174  1.3.14.1  wrstuden 	inf->data_size = get_uint32(&hdr->a_data);
    175  1.3.14.1  wrstuden 	inf->bss_size = get_uint32(&hdr->a_bss);
    176  1.3.14.1  wrstuden 	inf->entry_addr = get_uint32(&hdr->a_entry);
    177  1.3.14.1  wrstuden 	inf->text_off = sizeof(struct aout_m68k);
    178  1.3.14.1  wrstuden 	inf->data_off = sizeof(struct aout_m68k) + inf->text_size;
    179  1.3.14.1  wrstuden 	inf->text_pad = -inf->text_size & (AOUT_PAGESIZE(hdr) - 1);
    180  1.3.14.1  wrstuden 
    181  1.3.14.1  wrstuden 	return 0;
    182  1.3.14.1  wrstuden }
    183  1.3.14.1  wrstuden 
    184  1.3.14.1  wrstuden /*
    185  1.3.14.1  wrstuden  * digest ELF structure
    186  1.3.14.1  wrstuden  */
    187  1.3.14.1  wrstuden static int
    188  1.3.14.1  wrstuden open_elf(fn, fp, hdr, inf)
    189  1.3.14.1  wrstuden 	const char *fn;
    190  1.3.14.1  wrstuden 	FILE *fp;
    191  1.3.14.1  wrstuden 	struct elf_m68k_hdr *hdr;
    192  1.3.14.1  wrstuden 	struct exec_info *inf;
    193  1.3.14.1  wrstuden {
    194  1.3.14.1  wrstuden 	int i;
    195  1.3.14.1  wrstuden 	size_t nphdr;
    196  1.3.14.1  wrstuden 	struct elf_m68k_phdr phdr[2];
    197  1.3.14.1  wrstuden 
    198  1.3.14.1  wrstuden 	DPRINTF(("%s: is an ELF\n", fn));
    199  1.3.14.1  wrstuden 
    200  1.3.14.1  wrstuden 	if (hdr->e_ident[EI_VERSION] != EV_CURRENT ||
    201  1.3.14.1  wrstuden 	    get_uint32(&hdr->e_version) != EV_CURRENT) {
    202  1.3.14.1  wrstuden 		fprintf(stderr, "%s: unknown ELF version\n", fn);
    203  1.3.14.1  wrstuden 		return 1;
    204  1.3.14.1  wrstuden 	}
    205  1.3.14.1  wrstuden 
    206  1.3.14.1  wrstuden 	if (get_uint16(&hdr->e_type) != ET_EXEC) {
    207  1.3.14.1  wrstuden 		fprintf(stderr, "%s: not an executable\n", fn);
    208  1.3.14.1  wrstuden 		return 1;
    209  1.3.14.1  wrstuden 	}
    210  1.3.14.1  wrstuden 
    211  1.3.14.1  wrstuden 	if ((i = get_uint16(&hdr->e_machine)) != EM_68K) {
    212  1.3.14.1  wrstuden 		fprintf(stderr, "%s: wrong architecture (%d)\n", fn, i);
    213  1.3.14.1  wrstuden 		return 1;
    214  1.3.14.1  wrstuden 	}
    215  1.3.14.1  wrstuden 
    216  1.3.14.1  wrstuden 	if ((i = get_uint16(&hdr->e_shentsize)) != SIZE_ELF68K_SHDR) {
    217  1.3.14.1  wrstuden 		fprintf(stderr, "%s: size shdr %d should be %d\n", fn, i,
    218  1.3.14.1  wrstuden 			SIZE_ELF68K_SHDR);
    219  1.3.14.1  wrstuden 		return 1;
    220  1.3.14.1  wrstuden 	}
    221  1.3.14.1  wrstuden 
    222  1.3.14.1  wrstuden 	if ((i = get_uint16(&hdr->e_phentsize)) != SIZE_ELF68K_PHDR) {
    223  1.3.14.1  wrstuden 		fprintf(stderr, "%s: size phdr %d should be %d\n", fn, i,
    224  1.3.14.1  wrstuden 			SIZE_ELF68K_PHDR);
    225  1.3.14.1  wrstuden 		return 1;
    226  1.3.14.1  wrstuden 	}
    227  1.3.14.1  wrstuden 
    228  1.3.14.1  wrstuden 	if ((nphdr = get_uint16(&hdr->e_phnum)) != 1 && nphdr != 2) {
    229  1.3.14.1  wrstuden 		fprintf(stderr,
    230  1.3.14.1  wrstuden 			"%s: has %d loadable segments (should be 1 or 2)\n",
    231  1.3.14.1  wrstuden 			fn, nphdr);
    232  1.3.14.1  wrstuden 		return 1;
    233  1.3.14.1  wrstuden 	}
    234  1.3.14.1  wrstuden 
    235  1.3.14.1  wrstuden 	/* Read ELF program header table. */
    236  1.3.14.1  wrstuden 	if (fseek(fp, (foff_t) get_uint32(&hdr->e_phoff), SEEK_SET)) {
    237  1.3.14.1  wrstuden 		perror(fn);
    238  1.3.14.1  wrstuden 		return 1;
    239  1.3.14.1  wrstuden 	}
    240  1.3.14.1  wrstuden 	if (fread(phdr, sizeof phdr[0], nphdr, fp) != nphdr) {
    241  1.3.14.1  wrstuden 		fprintf(stderr, "%s: can't read ELF program header\n", fn);
    242  1.3.14.1  wrstuden 		return 1;
    243  1.3.14.1  wrstuden 	}
    244  1.3.14.1  wrstuden 
    245  1.3.14.1  wrstuden 	/* Just error checking. */
    246  1.3.14.1  wrstuden 	for (i = 0; i < (int) nphdr; i++) {
    247  1.3.14.1  wrstuden 		if (get_uint32(&phdr[i].p_type) != PT_LOAD) {
    248  1.3.14.1  wrstuden 			fprintf(stderr,
    249  1.3.14.1  wrstuden 				"%s: program header #%d is not loadable\n",
    250  1.3.14.1  wrstuden 				fn, i);
    251  1.3.14.1  wrstuden 			return 1;
    252  1.3.14.1  wrstuden 		}
    253  1.3.14.1  wrstuden 	}
    254  1.3.14.1  wrstuden 
    255  1.3.14.1  wrstuden 	if (nphdr == 1 && (get_uint32(&phdr[0].p_flags) & PF_W)) {
    256  1.3.14.1  wrstuden 		/*
    257  1.3.14.1  wrstuden 		 * Only one writable section --- probably "ld -N" executable.
    258  1.3.14.1  wrstuden 		 * Find out the start of data segment.
    259  1.3.14.1  wrstuden 		 */
    260  1.3.14.1  wrstuden 		struct elf_m68k_shdr shdr;
    261  1.3.14.1  wrstuden 		int nshdr;
    262  1.3.14.1  wrstuden 
    263  1.3.14.1  wrstuden 		nshdr = get_uint16(&hdr->e_shnum);
    264  1.3.14.1  wrstuden 
    265  1.3.14.1  wrstuden 		/* section #0 always exists and reserved --- skip */
    266  1.3.14.1  wrstuden 		if (nshdr > 1 &&
    267  1.3.14.1  wrstuden 		    fseek(fp,
    268  1.3.14.1  wrstuden 			  (foff_t) (get_uint32(&hdr->e_shoff) + sizeof shdr),
    269  1.3.14.1  wrstuden 			  SEEK_SET)) {
    270  1.3.14.1  wrstuden 			perror(fn);
    271  1.3.14.1  wrstuden 			return 1;
    272  1.3.14.1  wrstuden 		}
    273  1.3.14.1  wrstuden 		for (i = 1; i < nshdr; i++) {
    274  1.3.14.1  wrstuden 			if (fread(&shdr, sizeof shdr, 1, fp) != 1) {
    275  1.3.14.1  wrstuden 				fprintf(stderr,
    276  1.3.14.1  wrstuden 					"%s: can't read ELF section header\n",
    277  1.3.14.1  wrstuden 					fn);
    278  1.3.14.1  wrstuden 				return 1;
    279  1.3.14.1  wrstuden 			}
    280  1.3.14.1  wrstuden 
    281  1.3.14.1  wrstuden 			DPRINTF(("%s: section header #%d: flags 0x%x\n",
    282  1.3.14.1  wrstuden 				fn, i, get_uint32(&shdr.sh_flags)));
    283  1.3.14.1  wrstuden 
    284  1.3.14.1  wrstuden 			if (ELF68K_ISDATASEG(&shdr)) {
    285  1.3.14.1  wrstuden 				/*
    286  1.3.14.1  wrstuden 				 * data section is found.
    287  1.3.14.1  wrstuden 				 */
    288  1.3.14.1  wrstuden 				DPRINTF(("%s: one section, data found\n", fn));
    289  1.3.14.1  wrstuden 				inf->text_off = get_uint32(&phdr[0].p_offset);
    290  1.3.14.1  wrstuden 				inf->text_size = get_uint32(&shdr.sh_offset) -
    291  1.3.14.1  wrstuden 						 inf->text_off;
    292  1.3.14.1  wrstuden 				inf->text_pad = 0;
    293  1.3.14.1  wrstuden 				inf->data_off = inf->text_off + inf->text_size;
    294  1.3.14.1  wrstuden 				inf->data_size = get_uint32(&phdr[0].p_filesz) -
    295  1.3.14.1  wrstuden 						 inf->text_size;
    296  1.3.14.1  wrstuden 				inf->bss_size = get_uint32(&phdr[0].p_memsz) -
    297  1.3.14.1  wrstuden 						get_uint32(&phdr[0].p_filesz);
    298  1.3.14.1  wrstuden 				inf->entry_addr = get_uint32(&hdr->e_entry);
    299  1.3.14.1  wrstuden 				goto data_found;
    300  1.3.14.1  wrstuden 			}
    301  1.3.14.1  wrstuden 		}
    302  1.3.14.1  wrstuden 		/*
    303  1.3.14.1  wrstuden 		 * No data section found --- probably text + bss.
    304  1.3.14.1  wrstuden 		 */
    305  1.3.14.1  wrstuden 		DPRINTF(("%s: one section, no data section\n", fn));
    306  1.3.14.1  wrstuden 		inf->text_size = get_uint32(&phdr[0].p_filesz);
    307  1.3.14.1  wrstuden 		inf->data_size = 0;
    308  1.3.14.1  wrstuden 		inf->bss_size = get_uint32(&phdr[0].p_memsz) - inf->text_size;
    309  1.3.14.1  wrstuden 		inf->entry_addr = get_uint32(&hdr->e_entry);
    310  1.3.14.1  wrstuden 		inf->text_off = get_uint32(&phdr[0].p_offset);
    311  1.3.14.1  wrstuden 		inf->data_off = 0;
    312  1.3.14.1  wrstuden 		inf->text_pad = 0;
    313  1.3.14.1  wrstuden data_found:;
    314  1.3.14.1  wrstuden 	} else if (nphdr == 1) {
    315  1.3.14.1  wrstuden 		/*
    316  1.3.14.1  wrstuden 		 * Only one non-writable section --- pure text program?
    317  1.3.14.1  wrstuden 		 */
    318  1.3.14.1  wrstuden 		DPRINTF(("%s: one RO section\n", fn));
    319  1.3.14.1  wrstuden 		inf->text_size = get_uint32(&phdr[0].p_filesz);
    320  1.3.14.1  wrstuden 		inf->data_size = 0;
    321  1.3.14.1  wrstuden 		inf->bss_size = 0;
    322  1.3.14.1  wrstuden 		inf->entry_addr = get_uint32(&hdr->e_entry);
    323  1.3.14.1  wrstuden 		inf->text_off = get_uint32(&phdr[0].p_offset);
    324  1.3.14.1  wrstuden 		inf->data_off = 0;
    325  1.3.14.1  wrstuden 		inf->text_pad = get_uint32(&phdr[0].p_memsz) - inf->text_size;
    326  1.3.14.1  wrstuden 	} else {
    327  1.3.14.1  wrstuden 		/*
    328  1.3.14.1  wrstuden 		 * two sections
    329  1.3.14.1  wrstuden 		 * text + data assumed.
    330  1.3.14.1  wrstuden 		 */
    331  1.3.14.1  wrstuden 		int t = 0, d = 1, tmp;	/* first guess */
    332  1.3.14.1  wrstuden #define SWAP_T_D	tmp = t, t = d, d = tmp
    333  1.3.14.1  wrstuden 
    334  1.3.14.1  wrstuden 		DPRINTF(("%s: two sections\n", fn));
    335  1.3.14.1  wrstuden 
    336  1.3.14.1  wrstuden 		/* Find out text and data. */
    337  1.3.14.1  wrstuden 		if (get_uint32(&phdr[t].p_vaddr) > get_uint32(&phdr[d].p_vaddr))
    338  1.3.14.1  wrstuden 			SWAP_T_D;
    339  1.3.14.1  wrstuden 
    340  1.3.14.1  wrstuden 		if ((get_uint32(&phdr[t].p_flags) & PF_X) == 0 &&
    341  1.3.14.1  wrstuden 		    get_uint32(&phdr[d].p_flags) & PF_X)
    342  1.3.14.1  wrstuden 			SWAP_T_D;
    343  1.3.14.1  wrstuden 
    344  1.3.14.1  wrstuden 		if ((get_uint32(&phdr[d].p_flags) & PF_W) == 0 &&
    345  1.3.14.1  wrstuden 		    get_uint32(&phdr[t].p_flags) & PF_W)
    346  1.3.14.1  wrstuden 			SWAP_T_D;
    347  1.3.14.1  wrstuden #undef SWAP_T_D
    348  1.3.14.1  wrstuden 
    349  1.3.14.1  wrstuden 		/* Are the text/data sections correctly detected? */
    350  1.3.14.1  wrstuden 		if (get_uint32(&phdr[t].p_vaddr) >
    351  1.3.14.1  wrstuden 		    get_uint32(&phdr[d].p_vaddr)) {
    352  1.3.14.1  wrstuden 			fprintf(stderr, "%s: program sections not in order\n",
    353  1.3.14.1  wrstuden 				fn);
    354  1.3.14.1  wrstuden 			return 1;
    355  1.3.14.1  wrstuden 		}
    356  1.3.14.1  wrstuden 
    357  1.3.14.1  wrstuden 		if ((get_uint32(&phdr[t].p_flags) & PF_X) == 0)
    358  1.3.14.1  wrstuden 			fprintf(stderr, "%s: warning: text is not executable\n",
    359  1.3.14.1  wrstuden 				fn);
    360  1.3.14.1  wrstuden 
    361  1.3.14.1  wrstuden 		if ((get_uint32(&phdr[d].p_flags) & PF_W) == 0)
    362  1.3.14.1  wrstuden 			fprintf(stderr, "%s: warning: data is not writable\n",
    363  1.3.14.1  wrstuden 				fn);
    364  1.3.14.1  wrstuden 
    365  1.3.14.1  wrstuden 		inf->text_size = get_uint32(&phdr[t].p_filesz);
    366  1.3.14.1  wrstuden 		inf->data_size = get_uint32(&phdr[d].p_filesz);
    367  1.3.14.1  wrstuden 		inf->bss_size = get_uint32(&phdr[d].p_memsz) - inf->data_size;
    368  1.3.14.1  wrstuden 		inf->entry_addr = get_uint32(&hdr->e_entry);
    369  1.3.14.1  wrstuden 		inf->text_off = get_uint32(&phdr[t].p_offset);
    370  1.3.14.1  wrstuden 		inf->data_off = get_uint32(&phdr[d].p_offset);
    371  1.3.14.1  wrstuden 		inf->text_pad = get_uint32(&phdr[d].p_vaddr) -
    372  1.3.14.1  wrstuden 			(get_uint32(&phdr[t].p_vaddr) + inf->text_size);
    373  1.3.14.1  wrstuden 	}
    374  1.3.14.1  wrstuden 
    375  1.3.14.1  wrstuden 	return 0;
    376  1.3.14.1  wrstuden }
    377  1.3.14.1  wrstuden 
    378  1.3.14.1  wrstuden /*
    379  1.3.14.1  wrstuden  * open an executable
    380  1.3.14.1  wrstuden  */
    381  1.3.14.1  wrstuden FILE *
    382  1.3.14.1  wrstuden open_exec(fn, inf)
    383  1.3.14.1  wrstuden 	const char *fn;
    384  1.3.14.1  wrstuden 	struct exec_info *inf;
    385       1.1     itohy {
    386       1.1     itohy 	FILE *fp;
    387       1.1     itohy 	int i;
    388  1.3.14.1  wrstuden 	union {
    389  1.3.14.1  wrstuden 		struct aout_m68k	u_aout;
    390  1.3.14.1  wrstuden 		struct elf_m68k_hdr	u_elf;
    391  1.3.14.1  wrstuden 	} buf;
    392  1.3.14.1  wrstuden #define hdra	(&buf.u_aout)
    393  1.3.14.1  wrstuden #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.3.14.1  wrstuden 
    400  1.3.14.1  wrstuden 	/*
    401  1.3.14.1  wrstuden 	 * Check for a.out.
    402  1.3.14.1  wrstuden 	 */
    403  1.3.14.1  wrstuden 
    404  1.3.14.1  wrstuden 	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.3.14.1  wrstuden 	if ((i = AOUT_GET_MAGIC(hdra)) != AOUT_OMAGIC && i != AOUT_NMAGIC)
    410  1.3.14.1  wrstuden 		goto notaout;
    411  1.3.14.1  wrstuden 
    412  1.3.14.1  wrstuden 	if (open_aout(fn, hdra, inf))
    413       1.1     itohy 		goto out;
    414       1.1     itohy 
    415  1.3.14.1  wrstuden 	/* OK! */
    416  1.3.14.1  wrstuden 	return fp;
    417  1.3.14.1  wrstuden 
    418  1.3.14.1  wrstuden notaout:
    419  1.3.14.1  wrstuden 	/*
    420  1.3.14.1  wrstuden 	 * Check for ELF.
    421  1.3.14.1  wrstuden 	 */
    422  1.3.14.1  wrstuden 
    423  1.3.14.1  wrstuden 	if (hdre->e_ident[EI_MAG0] != ELFMAG0 ||
    424  1.3.14.1  wrstuden 	    hdre->e_ident[EI_MAG1] != ELFMAG1 ||
    425  1.3.14.1  wrstuden 	    hdre->e_ident[EI_MAG2] != ELFMAG2 ||
    426  1.3.14.1  wrstuden 	    hdre->e_ident[EI_MAG3] != ELFMAG3 ||
    427  1.3.14.1  wrstuden 	    hdre->e_ident[EI_CLASS] != ELFCLASS32 ||
    428  1.3.14.1  wrstuden 	    hdre->e_ident[EI_DATA] != ELFDATA2MSB) {
    429  1.3.14.1  wrstuden 		fprintf(stderr,
    430  1.3.14.1  wrstuden 		    "%s: not an OMAGIC or NMAGIC a.out, or a 32bit BE ELF\n",
    431  1.3.14.1  wrstuden 		    fn);
    432       1.1     itohy 		goto out;
    433       1.1     itohy 	}
    434       1.1     itohy 
    435  1.3.14.1  wrstuden 	/* ELF header is longer than a.out header.  Read the rest. */
    436  1.3.14.1  wrstuden 	if (fread(hdra + 1,
    437  1.3.14.1  wrstuden 		  sizeof(struct elf_m68k_hdr) - sizeof(struct aout_m68k),
    438  1.3.14.1  wrstuden 		  1, fp) != 1) {
    439  1.3.14.1  wrstuden 		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.3.14.1  wrstuden 	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.3.14.1  wrstuden #undef hdra
    452  1.3.14.1  wrstuden #undef hdre
    453       1.1     itohy }
    454       1.1     itohy 
    455       1.1     itohy /*
    456  1.3.14.1  wrstuden  * compare two executables and check if they are compatible
    457       1.1     itohy  */
    458       1.1     itohy int
    459  1.3.14.1  wrstuden check_2_exec_inf(inf1, inf2)
    460  1.3.14.1  wrstuden 	struct exec_info *inf1, *inf2;
    461       1.1     itohy {
    462       1.1     itohy 
    463  1.3.14.1  wrstuden 	if (inf1->text_size != inf2->text_size ||
    464  1.3.14.1  wrstuden 	    inf1->text_pad != inf2->text_pad ||
    465  1.3.14.1  wrstuden 	    inf1->data_size != inf2->data_size ||
    466  1.3.14.1  wrstuden 	    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.3.14.1  wrstuden  * 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.3.14.1  wrstuden 	struct exec_info inf1, inf2;
    565       1.1     itohy 	FILE *fpx = NULL;
    566       1.1     itohy 	struct huxhdr xhdr;
    567  1.3.14.1  wrstuden 	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.3.14.1  wrstuden 	 * open input executables and check them
    590       1.1     itohy 	 */
    591  1.3.14.1  wrstuden 	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.3.14.1  wrstuden 	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.3.14.1  wrstuden 	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.3.14.1  wrstuden 	 * get information of the executables
    611       1.1     itohy 	 */
    612  1.3.14.1  wrstuden 	textsize = inf1.text_size;
    613  1.3.14.1  wrstuden 	paddingsize = inf1.text_pad;
    614  1.3.14.1  wrstuden 	datasize = inf1.data_size;
    615  1.3.14.1  wrstuden 	execoff = inf1.entry_addr - loadadr1;
    616  1.3.14.1  wrstuden 
    617  1.3.14.1  wrstuden 	DPRINTF(("text: %u, data: %u, pad: %u, bss: %u, exec: %u\n",
    618  1.3.14.1  wrstuden 		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.3.14.1  wrstuden 	put_uint32(&xhdr.x_data, inf1.data_size);
    643  1.3.14.1  wrstuden 	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.3.14.1  wrstuden 	    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.3.14.1  wrstuden 	if (fseek(fpa1, inf1.text_off, SEEK_SET)) {
    664  1.3.14.1  wrstuden 		perror(fn1);
    665  1.3.14.1  wrstuden 		goto out;
    666  1.3.14.1  wrstuden 	}
    667  1.3.14.1  wrstuden 	if (fseek(fpa2, inf2.text_off, SEEK_SET)) {
    668  1.3.14.1  wrstuden 		perror(fn2);
    669  1.3.14.1  wrstuden 		goto out;
    670  1.3.14.1  wrstuden 	}
    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.3.14.1  wrstuden 	if (fseek(fpa1, inf1.data_off, SEEK_SET)) {
    684  1.3.14.1  wrstuden 		perror(fn1);
    685  1.3.14.1  wrstuden 		goto out;
    686  1.3.14.1  wrstuden 	}
    687  1.3.14.1  wrstuden 	if (fseek(fpa2, inf2.data_off, SEEK_SET)) {
    688  1.3.14.1  wrstuden 		perror(fn2);
    689  1.3.14.1  wrstuden 		goto out;
    690  1.3.14.1  wrstuden 	}
    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.3.14.1  wrstuden 	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.3.14.1  wrstuden 	    SIZE_ELF68K_HDR != 52 || SIZE_ELF68K_SHDR != 40 ||
    771  1.3.14.1  wrstuden 	    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.3.14.1  wrstuden 		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.3.14.1  wrstuden The input files must be static OMAGIC/NMAGIC m68k a.out executables\n\
    841  1.3.14.1  wrstuden or m68k ELF executables.\n\
    842  1.3.14.1  wrstuden 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