[gnu.utils.bug] patches for a byteswapping ld.c

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