ham@Neon.Stanford.EDU (Peter R. Ham) (09/01/89)
These patches allow ld to cross link on a little-endian machine and produce executables for a big-indian machine. In my case, ld compiled on a decstation-3100 and produced m68k executables. Byteswapping relocation information structures is probably different for various architecture combinations. This stuff doesn't work with COFF. Questions to me. 36,226d35 < /* < ** Byte swapping code. < */ < #ifdef MUST_BYTE_SWAP < #define WHEN_BYTE_SWAPPING(stmt) {stmt} < < void < byte_swap_long_in_place(src, count) < register char *src; < register int count; < /* Byte swap the longs in "src" without copying them anywhere. "count" < * gives the number of bytes to swap. It is truncated to an integral < * number of longwords (i.e. divisible by four). < */ < { < register char *dst = src + 3; < register unsigned int temp; < < count >>= 2; /* number of longs */ < < while (count-- > 0) < { < temp = *src; *src++ = *dst; *dst-- = temp; < temp = *src; *src++ = *dst; *dst-- = temp; < src += 2; < dst += 6; < } < } < < #define UR_BITS 3 /* lg(# of times loop unrolled) */ < #define UR_TIMES (1<<UR_BITS) /* # of times loop unrolled */ < #define UR_MASK (UR_TIMES - 1) < < void < byte_swap_short_copy(from, to, bytes) < register char *from, *to; < unsigned bytes; < { < register unsigned long temp; < register int shorts; < < shorts = (bytes>>1)+1; < while ((--shorts)&UR_MASK)/* until remainder is multiple of UR_TIMES */ < { < temp = *from++; < *to++ = *from++; < *to++ = temp; < } < < shorts >>= UR_BITS; /* n /= UR_TIMES, # of times for unrolled loop */ < while (--shorts >= 0) { < < #define STEP temp = *from++;*to++ = *from++;*to++ = temp; < < #if UR_BITS == 0 < STEP < #endif UR_BITS == 0 < < #if UR_BITS == 1 < STEP < STEP < #endif UR_BITS == 1 < < #if UR_BITS == 2 < STEP < STEP < STEP < STEP < #endif UR_BITS == 2 < < #if UR_BITS == 3 < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < #endif UR_BITS == 3 < < #if UR_BITS == 4 < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < STEP < #endif UR_BITS == 4 < < } < } /* byte_swap_short_copy */ < < < void < byte_swap_short_in_place(ptr, n) < char *ptr; < unsigned n; < { < byte_swap_short_copy(ptr, ptr, n); < } < < void < byte_swap_exec(x) < struct exec *x; < { < byte_swap_long_in_place(x, sizeof (struct exec)); < } < < byte_swap_nlist(x) < struct nlist *x; < { < byte_swap_long_in_place(&(x->n_un.n_strx), sizeof (x->n_un.n_strx)); < byte_swap_short_in_place(&(x->n_desc), sizeof (x->n_desc)); < byte_swap_long_in_place(&(x->n_value), sizeof (x->n_value)); < < } < < void < byte_swap_nlist_array(x, n) < struct nlist *x; < int n; < { < struct nlist *p = x; < < while ( p < ( x + n )) < { < byte_swap_nlist(p); < p++; < } < } < < byte_swap_relocation_info(relptr, relend) < struct relocation_info *relptr, *relend; < { < while (relptr < relend) < { < register unsigned char c; < register unsigned char *cp; < < byte_swap_long_in_place(relptr, 2*sizeof(long)); < cp = (unsigned char *)&((long *)relptr)[1]; < c = cp[0]; < cp[0] = cp[1]; < cp[1] = cp[2]; < cp[2] = cp[3]; < cp[3] = (c>>4) | /* move filler 4 bits */ < ((c&0x08)<<1) | /* move r_extern */ < ((c&0x06)<<4) | /* move r_length */ < ((c&0x01)<<7); /* move r_pcrel */ < relptr++; < } < } < < unbyte_swap_relocation_info(relptr, relend) < struct relocation_info *relptr, *relend; < { < while (relptr < relend) < { < register unsigned char c; < register unsigned char *cp; < < byte_swap_long_in_place(relptr, 2*sizeof(long)); < cp = (unsigned char *)&((long *)relptr)[1]; < c = cp[0]; < cp[0] = cp[1]; < cp[1] = cp[2]; /* These next two lines are a little suspect. */ < cp[2] = cp[3]; < cp[3] = (c<<4) | /* move filler 4 bits */ < ((c&0x10)>>1) | /* move r_extern */ < ((c&0x60)>>4) | /* move r_length */ < ((c&0x80)>>7); /* move r_pcrel */ < relptr++; < } < } < < #else < #define WHEN_BYTE_SWAPPING(stmt) < #endif < < 1607d1415 < WHEN_BYTE_SWAPPING(byte_swap_exec(&(entry->header));) 1634,1635c1442 < WHEN_BYTE_SWAPPING(byte_swap_nlist_array(entry->symbols, < entry->header.a_syms / (sizeof (struct nlist)));) --- > 1639c1446 < WHEN_BYTE_SWAPPING(byte_swap_long_in_place(&str_size, sizeof str_size);) --- > 3364d3170 < WHEN_BYTE_SWAPPING(byte_swap_exec(&outheader);) 3366d3171 < WHEN_BYTE_SWAPPING(byte_swap_exec(&outheader);) 3432,3435c3237 < WHEN_BYTE_SWAPPING(unbyte_swap_relocation_info(reloc, < reloc + < (entry->header.a_trsize / sizeof (struct relocation_info)));) < entry->textrel = reloc; --- > entry->textrel = reloc; 3448,3451d3249 < WHEN_BYTE_SWAPPING(unbyte_swap_relocation_info(reloc, < reloc + < (entry->header.a_drsize / sizeof (struct relocation_info)));) < 3491,3493d3288 < WHEN_BYTE_SWAPPING(unbyte_swap_relocation_info(reloc, < reloc + < (entry->header.a_trsize / sizeof (struct relocation_info)));) 3572,3574d3366 < WHEN_BYTE_SWAPPING(un_byte_swap_relocation_info(reloc, < reloc + < (entry->header.a_drsize / sizeof (struct relocation_info)));) 3697,3699d3488 < /* < ** A single byte does not need to be byte swapped. < */ 3707,3710d3495 < /* < ** A short DOES need to be byte swapped. < */ < WHEN_BYTE_SWAPPING(byte_swap_short_in_place((short *) (data + addr), sizeof (short));) 3715d3499 < WHEN_BYTE_SWAPPING(byte_swap_short_in_place((short *) (data + addr), sizeof (short));) 3719,3722d3502 < /* < ** A long DOES need to be byte swapped. < */ < WHEN_BYTE_SWAPPING(byte_swap_long_in_place((long *) (data + addr), sizeof (long));) 3727d3506 < WHEN_BYTE_SWAPPING(byte_swap_long_in_place((long *) (data + addr), sizeof (long));) 4108d3886 < WHEN_BYTE_SWAPPING(byte_swap_nlist_array(buf, bufp - buf);) 4121d3898 < WHEN_BYTE_SWAPPING(byte_swap_long_in_place(&strtab_size, sizeof strtab_size);) 4123d3899 < WHEN_BYTE_SWAPPING(byte_swap_long_in_place(&strtab_size, sizeof strtab_size);) 4233d4008 < WHEN_BYTE_SWAPPING(byte_swap_nlist_array(buf, bufp - buf);) -- Peter Ham PO Box 3430 (h)(415) 324-9645 MS Computer Science Student Stanford, CA ham@polya.stanford.edu Stanford University 94309 (o)(415) 723-2067