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